main script

main script

# jungle.py

# import sys, io, os, inspect
import numpy as np, pandas as pd; _=np
pd.set_option('display.precision', 6)
import matplotlib.pyplot as plt

# from dqsbt.util2 import util as aid # 加载数据
# from util import ttr                # 计算指标
# import candleplotter as cplt

# from qsutil import pkl
# from texttable import Texttable
# from packages import report as rp

# from qsutil import pkl; _cn_dict = pkl.pkl_load('d:/db/amipy/data/codename_dict.pkl')
import momentums_config as cfg
# import utility as ut
from qsutil import utility as ut
from qsutil import bbplot as bbp; _=bbp
import flower as fl; _=fl
p=dict(mfile='D:\\algolab\\study\\momentums\\momentums.py') # __file__
_pn = [n for n in dir(cfg) if not n.startswith('__')]
_pv = [getattr(cfg, n) for n in _pn]
p.update(dict(zip(_pn, _pv)))

from collections import namedtuple
# import pfbroker as pfb
_=namedtuple, 

import jungle as jg

def pre_proc():
    ''' 
    >>> ohlc, ind = pre_proc()
    '''
    ohlc, _codes, _dnames=ut.load(subset=cfg.subset)
    ind = ut.indicator(ohlc, n1=cfg.n1, n2=cfg.n2)
    return ohlc, ind




class RocAlgo(jg.Jungle):
    def __init__(self, 
                 cfg, ind, 
                 weight,
                 nComponent=2, 
                 nAdjustPos=5,
                 dbg=True,
        ):

        super().__init__(cfg, ind, 
                         nComponent=nComponent, nAdjustPos=nAdjustPos, dbg=dbg)
        self.weight = weight
        
    def run(self, ):
        mcdf = self.ind.loc[:, ('close roc'.split())]
        n = len(self.codes)
        for i, row in enumerate(mcdf.itertuples()):
            dt,clos, rocs = row[0], row[1:1+n], row[1+n:]
            dts = self.dt2dts(dt)
            close_dict={ k:v for k,v in  zip(self.codes, clos)}
            _ = dts, close_dict
            
            # 循环时最好依据数据出现的情况的顺序来处理, 
            # 比如首先遇到的是na值, 处理之. 很简单. 
            # 用continue来处理之(继续下一行的循环). 避免太多的elif语句
            if pd.isna(rocs[0]): continue
                
            # 开仓调仓日
            if i%self.nAdjustPos==0: 
                # 开仓
                if self.b.balance is None:
                    # print(i, dts, clos, rocs); _=input('pause')
                    buy_list, sorted_roc = self.sort_rocs(rocs)
                    self.price =[clos[i] for i in self.buy_iloc]
                    # 等权重配置方式
                    # 收盘前5分钟买入
                    code=buy_list
                    bbo = self.o.create_batch_buy_order(i, code,  percent=self.weight)
                    # print('最新订单:\n', self.o); print('\n历史订单:'); self.o.porders() # 最新订单和历史订单
                    self.b._first_batch_buy(bbo)
                    
                    # self.pause()
                    
                    # 收盘后收集收盘价
                    self.check_totcap(i)
    
                    # _=input('建仓之后pause')
                    
                # 调仓
                else:
                    buy_list, sorted_roc = self.sort_rocs(rocs)
                    self.price =[clos[i] for i in self.buy_iloc]
                    if sorted(buy_list)==sorted(self.get_ccc()):
                        # print('调仓日, 动量排序进榜个股与持仓个股名单相同, 无需操作.')
                        pass
                    # 动量选股之后, 有新的进榜个股
                    else:
                        print(f'调仓日: i={i}, buy_list={buy_list}, 头寸个股名单={self.get_ccc()}')
                        remove_gg, addon_gg = self.get_addon_remove(buy_list)
                        # print(f'卖出个股={remove_gg}, 买入个股={addon_gg}')
                        # Todo
                        # .  卖出头寸里的 退榜个股, 及时drop该席位: pos=pos.drop(psn, level=0)
                        # .  买入 新的进榜个股, 及时新建一个单行单列头寸: 设置psn=100+psn
                        #       other_pos=pd.DataFrame(), 
                        #       并联到头寸里: pos=pd.concat([pos, other_pos], axis=1)
                        # .  按照动量顺序重排头寸席位 
                        #       b.sort_position_seat(buylist)
                        
                        
                        if len(remove_gg)==1:
                            code=remove_gg[0]
                            so = self.o.create_sell_order(i, code, 0.)
                            self.b.sell_target_percent(so)
                        
                            if len(addon_gg)==1:
                                code=addon_gg[0]
                                # print(f'准备买入进榜个股={code}')
                                bo = self.o.create_buy_order(i, code, 0.5)
                                self.b.buy_target_percent(bo, buy_list)
                                
                        # 头寸合并,排序
                        # self.b.position = pd.concat([self.b.position, self.b.other_pos], axis=1)
                        self.b.sort_position_seat(buy_list)
                        # print(self.o)
                        # print(self.b.get_position())
                        
                        # self.pause()

                    # 收盘后查资
                    self.check_totcap(i)
    
                    # _=input('建仓之后pause')
                    
            # 非调仓日
            else: 
                # 尚未建仓时
                if self.b.balance==None:
                    pass
                # 有仓位时
                elif self.get_v0()>0:#第一号仓位有的
                    self.check_totcap(i)
                    pass
                # 空仓时, 只登记个时间戳而已
                elif self.get_v0()==0:
                    self.log_dt() # 
                    pass
    
        print(f'nAdjustPos={self.nAdjustPos}, totcap={self.b.totcap:.2f}')
        # self.post_proc()
        # self.draw_c0()
        # self.check_result()
    
#%%


def utest2(cfg, ind, nAdjustPos=5, nComponent=2, weight=(0.5, 0.5)):
    '''
    >>> ohlc, ind = pre_proc()
    >>> jgl = utest2(cfg, ind, 8, 2, (0.5, 0.5)) # 14.4w
    >>> jgl = utest2(cfg, ind, 4, 2, (0.9, 0.1)) # 15.5w
    >>> jgl = utest2(cfg, ind, 4, 3, (0.6, 0.2, 0.2)) # 15.5w
    '''
    jgl = RocAlgo(cfg, ind, 
                  weight=weight, 
                  nComponent=nComponent,
                  nAdjustPos=nAdjustPos, 
    ) 
    jgl.run()
    return jgl



def save_etf(start_date='1900-01-01', end_date='2020-12-31'):
    ''' 下载主要etf数据, 并且保存到db. 
    >>> op=DbOperation()
    >>> op.save_etf()
    df_dict = save_etf()
    '''
    import util.tdxhq as hq, time
    start_date='2020-01-01'
    major_etf_codes = '512880 512660 512800 512170 159928'.split()
    print('Downloading 主要etf的日线数据 from tdxhq......\n')
    print(f"start date = {start_date:s}, end date={end_date:s}")
    df_dict={}
    for i, code in enumerate(major_etf_codes):
        print(f'{i:2d}', 'downloading.......:' , code)
        df=hq.test_get_k_data(code, sdate=start_date, edate=end_date)
        df.index=pd.DatetimeIndex(df.index)
        
        df = df.assign(code=code[:6])
        df = df.rename(columns={'vol':'volume'})
        # df = df.drop(columns='date')
        # cols = list(df)
        cols = 'open high low close volume amount code'.split()
        df = df.loc[:, cols]
        # df.to_sql('table_etf', conn, if_exists='append', dtype={'code':'CHAR'})
        time.sleep(2)
        df_dict.update({code:df})
    return df_dict

def _draw(df_dict):
    fig, ax = plt.subplots(len(df_dict), 1)    
    for i, (k,v) in enumerate(df_dict.items()):
        (v.close/v.close[0]).plot(ax=ax[i], label=k, legend=True)
    
    fig, ax = plt.subplots(1, 1)    
    for i, (k,v) in enumerate(df_dict.items()):
        (v.close/v.close[0]).plot(ax=ax, label=k, legend=True)
    

posted @ 2022-01-27 20:26  duanqs  阅读(65)  评论(0编辑  收藏  举报