zoukankan      html  css  js  c++  java
  • simulation

    simulation

    
    # -*- coding: utf-8 -*-
    """strat_sz100iw.py
    一种趋势策略的尝试, 针对深证100指数周线数据
    """
    import os, pathlib, datetime; type(os); type(pathlib)
    import pandas as pd; type(pd)
    import numpy as np; type(np)
    import matplotlib.pyplot as plt
    
    from copy import deepcopy
    from collections import OrderedDict ; type(OrderedDict)
    
    import toolkit.myDataIO as mdio
    import util.ttr as ttr     
    
    import strat_sz100iw_report as wr; type(wr)
    
    import imp; type(imp)
    #imp.reload(mdio)
    #imp.reload(ttr)
    
    class GlobalEnv:
        pass
    global g
    g=GlobalEnv()  # 初始化一个全局对象, 用于存储全局变量
    g.params=OrderedDict(
            atr_n=14, delta=0.5, sig_filter_n=3, 
            start_year=None, 
            code='399330',
            maxloss_pct=0.20,
            )
    
    
    #def simulation_LineMode(atr_n, delta, sig_filter_n, start_year=None, code='399330'):
    def simulation_LineMode(**kwargs):
        '''
        '''
        global g
        atr_n       =kwargs['atr_n']
        delta       =kwargs['delta']
        sig_filter_n=kwargs['sig_filter_n']
        start_year  =kwargs['start_year']
        code        =kwargs['code']
        with_plot   =kwargs['with_plot']
        
        fname = 'd:/new_haitong/T0002/export/{}.txt'.format(code)
        
        with open(fname, encoding='gbk') as f:
            first_line_data=f.readline()    
            asset_name=first_line_data.strip()
            title_='标的资产的代码和名称是: {}'.format(asset_name)
            print(title_)
            print('+'*(len(title_) + ttr.cchar(title_)))
        
        ohlc_ = mdio.read_tdxExport_txtFile(fname)
        ohlc=ohlc_[0]
        ohlc=ohlc.iloc[:, 0:5]
        
        if start_year:
            ohlc = ohlc[start_year:]
        out, perf_dict = ttr.strat_sz100iw(ohlc, atr_n, delta, sig_filter_n, start_year)
    
        if with_plot:
            fig, ax=plt.subplots(1,1)
            ohlc.close.plot(ax=ax)
            out.bprice.plot(ax=ax)
            out.sprice.plot(ax=ax)
            out.equity.plot()
        print('End equity : {:12.2f}'.format(out.equity[-1] ,))
        [print('{0:{2:}s} : {1:}'.format(k, v, (15-ttr.cchar(k)))) for k, v in perf_dict.items()]
        print()
        return out
    
    
    def simulation_BarMode(df, **kwargs): #maxloss_pct=0.20):
        global g
        #g.params.append(maxloss_pct)
        maxloss_pct= kwargs['maxloss_pct']
        code       = kwargs['code']
        
        c=df.close
        trend=df.trend; type(trend)
        ctx_bsig=df.b_sig
        ctx_ssig=df.s_sig
        ctx_check, hold_dict, ctx_pos, pos_dict = [], {}, [], {}
        order='empty'
        
        days = df.index[40:-1]
        _15hours = datetime.timedelta(0,15*3600); type(_15hours)
        _9hours = datetime.timedelta(0,9*3600)
        _930hours = datetime.timedelta(0,9.5*3600)
        #ohlc.index.to_pydatetime() + _15hours
        for enum, tdate in enumerate(days):
            loc      = df.index.get_loc(tdate) + 1
            the_days = df.index[ (loc-5):loc]
            # 回测当天
            today = the_days[-1]
            # 上一个交易日
            yesterday = the_days[-2]    
            if enum%60==0: 
                #math.fmod(5, 3), 取模数, 求取除运算余数
                # every 60 bars, print a timestamps of the process
                print('''+++交易日期是: {}, {}'''.format(today,yesterday))
        
            ###############  检查交易信号
            ssig = ctx_ssig.loc[yesterday]
            bsig = ctx_bsig.loc[yesterday]
            preclose = c.loc[yesterday]
            todayopen_    = df.open[today]
            todayclose    = df.close[today]
            ydtrend        = df.trend[yesterday]
            check_dict = OrderedDict(
                    dt=today.to_pydatetime() + _9hours,
                    bsig=bsig,
                    ssig=ssig,
                    preclose=preclose,
                    todayopen=todayopen_,
                    todayclose=todayclose,
                    comment= '牛股:伺机做多' if preclose > ydtrend  else '熊股:少碰' 
                    )
            ctx_check.append(check_dict)
            
            ###############  制定/给出下单命令: 检查头寸, 检查浮动盈亏/持仓天数, 然后定出结论
            if hold_dict=={}:
                if bsig:
                    order = '开仓'
                else:
                    order ='空仓寻进'; # print('order=wait',yesterday,wait)
            else:
                if ssig:
                    order = '清仓'
                elif pos_dict!={} and pos_dict['fpnl']<-maxloss_pct :
                    order = '止损'
                else:
                    order = '满仓寻出'
            # 4种情况汇总起来应该是一个完整的集合, 不能有遗漏; 否则逻辑上有漏洞
                pass
            
            if hold_dict!={}:
                fpnl, hold_days = pos_dict['fpnl'], pos_dict['hold_days']
                stoploss_hp   = abs(fpnl)<5 and hold_days>5  # 横盘太久应该出局观望
                stoploss_5pct = fpnl<-5  # 建仓之后很快亏损, 到达一定幅度的话应该亏本出局
                stopprft_cg   = fpnl>20  # 快速冲高, 浮盈很快到达一定幅度后应该卖出, 等回落后再买进
                type((stoploss_5pct,stoploss_hp, stopprft_cg))
        
            ###############  照单执行命令
            if order=='开仓':
                buy_date = today.to_pydatetime() + _930hours
                pos_dict = OrderedDict(
                        order = order,
                        dt = today.to_pydatetime(),
                        buy_date=buy_date,
                        buy_price=todayopen_,
                        hold_days=0, position=1, 
                        fpnl = 0.0,  # preclose/buy_price,
                        
                        )
                ### 保留头寸字典到列表里(头寸字典在循环过程中, 每天都在变化的, 而且在清仓时会变成空字典)
                ### 一定要用上deepcopy方法, 
                ### 字典的深复制对象不会遭受到源字典的动态变化(依据收盘价不断修改键值)的影响
                ctx_pos.append(deepcopy(pos_dict)) 
                #hold_dict[g.code]=[buy_date, todayopen_]
                hold_dict[code]=[buy_date, todayopen_]
            
            if order=='清仓' or order=='止损':
                pos_dict['order'] = order
                pos_dict['dt'] =  today.to_pydatetime() #+ _930hours
                pos_dict['sell_date']  = today.to_pydatetime() + _930hours
                pos_dict['sell_price'] = round(todayopen_,3)
                pos_dict['ratio']      = round(100*((todayopen_/pos_dict['buy_price']) - 1),2)
                pos_dict['fpnl'] = todayopen_/pos_dict['buy_price'] -1
                pos_dict['params'] = g.params#(3,20, 1.5, 1, 5)
                pos_dict['position']=0.0
                ctx_pos.append(deepcopy(pos_dict))
        
        
                del hold_dict[code]
                
            if order=='满仓寻出':
                pos_dict['order'] = order
                pos_dict['dt'] =  today.to_pydatetime() #+ _9hours
                pos_dict['hold_days'] += 1
                pos_dict['fpnl'] = preclose/pos_dict['buy_price'] -1
                pos_dict['position']=1.0
                ctx_pos.append(deepcopy(pos_dict))
    
            if order=='空仓寻进':
                del pos_dict; pos_dict=OrderedDict()
                pos_dict['order'] = order
                pos_dict['dt'] =  today.to_pydatetime() #+ _930hours
                pos_dict['position']=0.0
                ctx_pos.append(deepcopy(pos_dict))
    
    
        
        check_df = pd.DataFrame(ctx_check); type(check_df)
        pos = pd.DataFrame(ctx_pos)
        return pos
    
    
    def simu_with_stoploss(atr_n=14, delta=0.5, sig_filter_n=3, 
                           start_year=None, 
                           code='399330',
                           maxloss_pct=0.20, 
                           trx_timing='closing',  
                           with_plot=False,
                           ):   
        '''
        >>> pos,cagr=simu_with_stoploss(maxloss_pct=0.12)  #### 不错的止损值
        >>> pos,cagr=simu_with_stoploss(maxloss_pct=0.12, trx_timing='opening')  #### 不错的止损值
        
        >>> pos=simu_with_stoploss(maxloss_pct=0.2)
        >>> pos=simu_with_stoploss(maxloss_pct=0.11)
        >>> pos=simu_with_stoploss(atr_n=13, maxloss_pct=0.12) 
        >>> pos=simu_with_stoploss(atr_n=16, maxloss_pct=0.12) 
        >>> pos=simu_with_stoploss(maxloss_pct=0.15)
        
    
    
    参数: OrderedDict(
    [('atr_n', 14), ('delta', 0.5), ('sig_filter_n', 3), ('start_year', None), ('code', '399330'), 
    ('maxloss_pct', 0.12), ('trx_timing', 'closing'), ('with_plot', False)])
    
        下单指令集合: {'满仓寻出', '止损', '开仓', '空仓寻进', '清仓'}
    
    dk          的次数:     49
    dp          的次数:     45
    gr          的次数:      4
    hold_equity 的次数:    264
    hold_cash   的次数:    326
    
    end_equity        : 11541.354   if trx_timing=='opening'
    end_nav           : 12.003      7.996
    cagr              : 0.19        0.156
    mdd               : 0.235       0.274
    sharpe            : 1.151
    annu_volatility   : 0.165
    净值的标准差      : 0.023    
        '''
        global g
        g.params=OrderedDict(
                atr_n=atr_n, delta=delta, sig_filter_n=sig_filter_n, 
                start_year=start_year, 
                code=code,
                maxloss_pct=maxloss_pct, 
                trx_timing=trx_timing, 
                with_plot=with_plot, 
                )
        #df  = simulation_LineMode(atr_n, delta, sig_filter_n, start_year, '399330')
        #pos = simulation_BarMode(df, maxloss_pct)
        df  = simulation_LineMode(**g.params)
        pos = simulation_BarMode(df, **g.params)
        pos = pos.set_index('dt', drop=False)
        
        print('
    参数: {}'.format(g.params))
        print('
    下单指令集合: {}
    '.format(set(pos.order)))
        order_group_dict = OrderedDict(
                dk = pos.order[pos.order=='开仓'].count(), # 多开,
                dp = pos.order[pos.order=='清仓'].count(), # 多平
                gr = pos.order[pos.order=='止损'].count(),  # 割肉, stoploss
                hold_equity = pos.order[pos.order=='满仓寻出'].count(),
                hold_cash   = pos.order[pos.order=='空仓寻进'].count(),
                )
        [print('{:12s}的次数: {:6d}'.format(k,v)) for k,v in order_group_dict.items()]
        
        pos_=pos.reindex(df.index)
        pos_.position.fillna(0.0, inplace=True)
        #print(set(pos_.position))
        roc1=df.close.pct_change().fillna(0)
        #交割时机的把握逻辑:
        #收盘时刻观察信号, 按收盘价成交:
        if trx_timing=='closing':
            eq = (1+roc1*pos_.position).cumprod() * df.close[0]
        elif trx_timing=='opening':
            roc1_B = ttr.IF((df.b_sig.shift(1)>0, (df.open/df.close.shift(1)-1), roc1))
            roc1_C = ttr.IF((df.s_sig>0,          (df.open.shift(-1)/df.close.shift(1)-1), roc1_B))
            eq = (1+roc1_C * pos_.position).cumprod() * df.close[0]
        pos_['open']=df.open
        pos_['close']=df.close
        pos_['equity']=eq
        
    
        perf_dict=ttr.perf(pos_)
        print()
        #[print('{:15s} : {}'.format(k, v)) for k, v in perf_dict.items()]
        for k, v in perf_dict.items():
            pwidth = 17 - ttr.cchar(k)
            print('{1:{0:}s} : {2:}'.format(pwidth, k, v)) 
        print()
    
        if with_plot:
            fig, ax=plt.subplots(1,1)
            pos_.close.plot(ax=ax)
            #out.bprice.plot(ax=ax)
            #out.sprice.plot(ax=ax)
            pos_.equity.plot()
        
        return pos_, perf_dict['cagr']
    
    
    #%%
    def opt(trx_timing='closing'):
        '''参数寻优
        最佳参数大概为: 14 atr_n, 12 maxloss_pct, 'closing' trx_timing
        >>> opt(trx_timing='closing')
        >>> opt(trx_timing='opening')
    
        atr_n  maxloss_pct   cagr
    0      12         0.05  0.141
    1      12         0.10  0.149
    2      12         0.15  0.148
    3      13         0.05  0.158
    4      13         0.10  0.176
    5      13         0.15  0.175
    6      14         0.05  0.151
    7      14         0.10  0.179
    8      14         0.15  0.180
    9      15         0.05  0.140
    10     15         0.10  0.145
    11     15         0.15  0.155
    12     16         0.05  0.138
    13     16         0.10  0.157
    14     16         0.15  0.156
    15     17         0.05  0.120
    16     17         0.10  0.139
    17     17         0.15  0.135
    18     18         0.05  0.132
    19     18         0.10  0.143
    20     18         0.15  0.143  
    
    if 次日开盘成交: 那么结果如下: 结论是: 成交时机应该选择当日尾盘(cagr能有3%的提升)
        atr_n  maxloss_pct   cagr
    0      12         0.05  0.096
    1      12         0.10  0.103
    2      12         0.15  0.103
    3      13         0.05  0.130
    4      13         0.10  0.146
    5      13         0.15  0.145
    6      14         0.05  0.118
    7      14         0.10  0.146
    8      14         0.15  0.147
    9      15         0.05  0.102
    10     15         0.10  0.105
    11     15         0.15  0.114
    12     16         0.05  0.107
    13     16         0.10  0.125
    14     16         0.15  0.124
    15     17         0.05  0.088
    16     17         0.10  0.105
    17     17         0.15  0.102
    18     18         0.05  0.089
    19     18         0.10  0.098
    20     18         0.15  0.098    
    
        '''
        opt_summary=pd.DataFrame()
        for atr_n in range(12, 19):
            for maxloss_pct in [0.05, 0.10, 0.15]:
                pos, cagr=simu_with_stoploss(atr_n=atr_n, maxloss_pct=maxloss_pct, trx_timing=trx_timing) 
                opt_summary = opt_summary.append( 
                        pd.DataFrame(OrderedDict(
                                atr_n=atr_n, 
                                maxloss_pct=maxloss_pct, 
                                cagr=cagr), 
                                index=[1,] ),
                        ignore_index=True,
                        )
        print(opt_summary)
        
    
    
    
    #%%
    #wr.write_report_md()
    #%%
    
    if __name__=="__main__": 
        #atr_n=int(input('Please enter parameter: atr_n: '))
        #for atr_n in range(12, 18):
        pass
    
    
    
    
  • 相关阅读:
    HTML+CSS笔记 CSS进阶续集
    HTML+CSS笔记 CSS进阶
    HTML+CSS笔记 CSS入门续集
    HTML+CSS笔记 CSS入门
    test
    Python Paramiko模块安装和使用
    RedHat升级Python到2.7.6
    python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
    5、使用EF对后台SysSample数据增删改查
    4、创建SQL数据库,添加EF实体数据模型
  • 原文地址:https://www.cnblogs.com/duan-qs/p/12913330.html
Copyright © 2011-2022 走看看