zoukankan      html  css  js  c++  java
  • simulation 2

    
    # -*- coding: utf-8 -*-
    """strat_sz100iw.py
    一种趋势策略的尝试, 针对深证100指数周线数据
    """
    import itertools
    import os, pathlib, datetime; type(os); type(pathlib);type(datetime)
    import pandas as pd; type(pd)
    import numpy as np; type(np)
    import matplotlib.pyplot as plt
    
    from copy import deepcopy;type(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)
    
    global g
    g=ttr.GlobalEnv()
    g.params=OrderedDict(
            atr_n=14, delta=0.5, sig_filter_n=3, 
            start_year=None, 
            code='399330',
            maxloss_pct=0.12,
            with_plot=False,
            )
    #%%
    
    #def simulation_LineMode(atr_n, delta, sig_filter_n, start_year=None, code='399330'):
    def simulation_LineMode(**kwargs):
        '''
        Python里的可变参数(*和**字头的参数):
        在函数应用中(被定义或者被调用), 
        有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。
        此时,可用包裹(packing)位置参数/包裹型位置参数,或者包裹型关键字参数,
        来进行参数传递, 会显得非常方便灵活。
        
        关键字参数(双星号字头的参数)允许你传入0个或任意个含参数名的参数,
        这些关键字参数在函数内部会自动组装为一个dict.
    
        >>> df_line=simulation_LineMode(**g.params) 
        atr14_pct=ttr.atr(df_line,14)/df_line.close *100
        atr14_pct.quantile() # 4.85%
        atr14_pct.describe()
        
        count    716.000000
        mean       5.476807
        std        2.481463
        min        2.134225
        25%        3.923625
        50%        4.851406
        75%        6.285523
        max       15.688897
        
        所以: stoploss的选择: 应该 > mean (or 1/2 quantile)
        '''
        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_)))
        g.title_info=OrderedDict(
                fname=fname,
                asset_name=asset_name,
                )
        
        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_lm(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, (18-ttr.cchar(k)))) for k, v in perf_dict.items()]
        print()
        return out
    
    #%%
    
    def simu_with_stoploss(atr_n=14, delta=0.5, sig_filter_n=3, 
                           start_year=None, 
                           code='399330',
                           
                           signal_type=1, # exRemoved, 0=original
                           maxloss_pct=0.11, 
                           stoploss_mode=1, # (0, 1)分别表示当日尾盘止损, 次日尾盘止损
                           trx_timing='closing',  
                           with_plot=False,
                           ):   
        '''
        >>> reset -f
        
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, signal_type=1, stoploss_mode=1, with_plot=False, trx_timing='closing')  #### 不错的止损值
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, signal_type=0, stoploss_mode=1, with_plot=False, trx_timing='closing')  #### 不错的止损值
        
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=1, with_plot=False, trx_timing='opening')  #
        
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=0, with_plot=False, trx_timing='closing')  #
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.13, stoploss_mode=0, with_plot=False, trx_timing='opening')  #
      
        >>> pos,cagr,mdd,sharpe = simu_with_stoploss(maxloss_pct=0.11, stoploss_mode=0, with_plot=True)  #### 不错的止损值
        >>> pos,cagr,mdd,sharpe=simu_with_stoploss(maxloss_pct=0.12, trx_timing='opening')  #### 不错的止损值
        
    
    参数: 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, 方便调用函数时使用.
        g.params=OrderedDict(
                atr_n=atr_n, delta=delta, sig_filter_n=sig_filter_n, 
                start_year=start_year, 
                code=code,
                
                signal_type=signal_type,
                trx_timing=trx_timing, 
                maxloss_pct=maxloss_pct, 
                stoploss_mode=stoploss_mode, 
                
                with_plot=with_plot, 
                )
        
        df  = simulation_LineMode(**g.params)
        # print(df.columns)
        # Index(['open', 'high', 'low', 'close', 'trend', 
        # 'b_sig', 's_sig', 'bprice', 'sprice', 'buybars', 'sellbars', 
        # 'pos', 'equity', 'b22_sig', 's22_sig'],
        
        pos = ttr.simulation_BarMode(df, **g.params)
        pos = pos.set_index('dt', drop=False)
        
        print('
    参数: {}'.format(g.params))
        ttr.print_orders_count(pos)
           
        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: 应该为: 该日收盘价 to 该日开盘价
            #roc1_B = ttr.IF((df.b_sig.shift(1)>0, (df.open/df.close.shift(1)-1), roc1))
            roc1_B = ttr.IF((df.b_sig.shift(1)>0, (df.close/df.open-1), roc1))
            # 校正持仓最后日的roc1: 应该为: 次日开盘价 to 昨日收盘价
            # 下述方法仅保证了正常卖出时的收益率的正确性, 止损时的情形需要完善.
            #roc1_C = ttr.IF((df.s_sig>0,   (df.open.shift(-1)/df.close.shift(1)-1), roc1_B))
            exit_case = ttr.downCross(pos_.position, 0.5).shift(-1)
            roc1_C = ttr.IF(  (exit_case>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 = 18 - 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'], perf_dict['mdd'], perf_dict['sharpe']
    
    
    #%%
    def opt(trx_timing='closing', stoploss_mode=1, signal_type=1,):
        '''参数寻优
        最佳参数大概为: 
            14        atr_n, 
            13%       maxloss_pct, 
            'closing' trx_timing
            1         stoploss_mode (次日止损)
        绩效指标:
             CAGR   MDD     SHARPE
             19.5%  23.5%   1.180
             
             
        >>> opt_df=opt(trx_timing='closing', stoploss_mode=1, )
        >>> opt_df=opt(trx_timing='closing', stoploss_mode=1, signal_type=0) #用了原始信号后, 结果较差
        >>> opt_df=opt(trx_timing='opening', stoploss_mode=1)
        
        >>> opt_df=opt(trx_timing='closing', stoploss_mode=0, )
        >>> opt_df=opt(trx_timing='opening', stoploss_mode=0, signal_type=0) #更差
    
        stoploss_mode trx_timing  atr_n  maxloss_pct   cagr    mdd  sharpe
    0               1    closing     13         0.05  0.173  0.359   1.107
    1               1    closing     13         0.08  0.171  0.395   1.043
    2               1    closing     13         0.11  0.181  0.395   1.098
    3               1    closing     13         0.14  0.187  0.395   1.093
    4               1    closing     14         0.05  0.160  0.248   1.058
    5               1    closing     14         0.08  0.167  0.318   1.047
    6               1    closing     14         0.11  0.184  0.235   1.142
    7               1    closing     14         0.14  0.189  0.235   1.135
    
    8               1    closing     15         0.05  0.152  0.391   0.987
    9               1    closing     15         0.08  0.142  0.426   0.886
    10              1    closing     15         0.11  0.150  0.445   0.923
    11              1    closing     15         0.14  0.161  0.407   0.950
    
    
    if 次日开盘成交: 那么结果如下: 
        成交时机选择当日尾盘略微好一点点(cagr能有3%的提升)
        但是没有明显的优势
        stoploss_mode trx_timing  atr_n  maxloss_pct   cagr    mdd  sharpe
    0               1    opening     13         0.05  0.161  0.376   1.037
    1               1    opening     13         0.08  0.165  0.376   1.010
    2               1    opening     13         0.11  0.185  0.376   1.114
    3               1    opening     13         0.14  0.176  0.392   1.022
    4               1    opening     14         0.05  0.153  0.245   1.019
    5               1    opening     14         0.08  0.160  0.310   1.013
    6               1    opening     14         0.11  0.187  0.222   1.159
    
    7               1    opening     14         0.14  0.180  0.222   1.076
    8               1    opening     15         0.05  0.139  0.378   0.908
    9               1    opening     15         0.08  0.134  0.378   0.842
    10              1    opening     15         0.11  0.154  0.378   0.942
    11              1    opening     15         0.14  0.151  0.383   0.879
    
        '''
        global g
        
        #把参数字典, 通过笛卡尔乘积, 转换为参数数据框
        par_dict = OrderedDict(
                        atr_n=range(13,16),
                        #maxloss_pct=np.arange(5,17,1)/100,
                        maxloss_pct=np.arange(5,17,1)/100,
                        )
        prod = itertools.product(*tuple(par_dict.values())) # 传递包裹型位置参数
        par_df = pd.DataFrame(list(prod), columns=par_dict.keys())
    
        out=pd.DataFrame()
        opt_summary=pd.DataFrame()
        for (i, atr_n, maxloss_pct ) in par_df.itertuples():
            pos, cagr, mdd, sharpe = simu_with_stoploss(
                    atr_n=atr_n, 
                    maxloss_pct=maxloss_pct, 
                    signal_type=signal_type, 
                    trx_timing=trx_timing, 
                    stoploss_mode=stoploss_mode) 
            
            out['equity{}'.format(i)]=pos.equity
            opt_summary = opt_summary.append( 
                        pd.DataFrame(
                            OrderedDict(
                            atr_n=atr_n, 
                            maxloss_pct=maxloss_pct, 
                            stoploss_mode=g.params['stoploss_mode'],
                            trx_timing=g.params['trx_timing'],
                            cagr=cagr, mdd=mdd, sharpe=sharpe
                            ), 
                        index=[1], 
                        ),
                    ignore_index=True,
                    )
        print(opt_summary)
        out['close']=pos.close
        
    #    out.plot()
        return out
        
    
    
    
    #%%
    #wr.write_report_md()
    #%%
    
    if __name__=="__main__": 
        #atr_n=int(input('Please enter parameter: atr_n: '))
        #for atr_n in range(12, 18):
        pass
    
    
    
  • 相关阅读:
    【洛谷P3628】特别行动队
    【洛谷P3233】世界树
    【BZOJ1597】土地购买
    【洛谷P4068】数字配对
    【洛谷P3899】谈笑风生
    【BZOJ2726】任务安排
    【洛谷P6186】[NOI Online 提高组] 冒泡排序
    【洛谷P3369】【模板】普通平衡树
    【UOJ#8】Quine
    标准 插入flash
  • 原文地址:https://www.cnblogs.com/duan-qs/p/12927594.html
Copyright © 2011-2022 走看看