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
    
    
    
    
  • 相关阅读:
    Sitecore Digital Marketing System, Part 1: Creating personalized, custom content for site visitors(自定义SiteCore中的 Item的Personalize的Condition) -摘自网络
    Send email alert from Performance Monitor using PowerShell script (检测windows服务器的cpu 硬盘 服务等性能,发email的方法) -摘自网络
    使用Mono Cecil 动态获取运行时数据 (Atribute形式 进行注入 用于写Log) [此文报考 xxx is declared in another module and needs to be imported的解决方法]-摘自网络
    秒杀 ILSpy 等反编译利器 DotNet Resolver
    Nagios:企业级系统监控方案
    C# Asp.net中的AOP框架 Microsoft.CCI, Mono.Cecil, Typemock Open-AOP API, PostSharp -摘自网络 (可以利用反射 Attribute 进行面向切面编程 可以用在记录整个方法的Log方面)
    Windows性能监视器之CPU、硬盘、IO等监控方法详解-摘自网络
    网站防刷方案 -摘自网络
    利用XSD配合XSLT產出特定格式Word檔案 -摘自网络
    asp页面快速找到菜单按钮转向的页面的方法
  • 原文地址:https://www.cnblogs.com/duan-qs/p/12913330.html
Copyright © 2011-2022 走看看