基本分析

策略分享
标签: #<Tag:0x00007f61deb93bc8>

(lj001) #1
克隆策略
In [1]:
# 基础参数配置
class conf:
    start_date = '2010-01-01'
    end_date='2017-04-01'
    # split_date 之前的数据用于训练,之后的数据用作效果评估
    split_date = '2015-01-01'
    # D.instruments: https://bigquant.com/docs/data_instruments.html
    instruments = D.instruments(start_date, end_date)

    # 机器学习目标标注函数
    # 如下标注函数等价于 max(min((持有期间的收益 * 100), -20), 20) + 20 (后面的M.fast_auto_labeler会做取整操作)
    # 说明:max/min这里将标注分数限定在区间[-20, 20],+20将分数变为非负数 (StockRanker要求标注分数非负整数)
    label_expr = ['return * 100', 'where(label > {0}, {0}, where(label < -{0}, -{0}, label)) + {0}'.format(20)]
    # 持有天数,用于计算label_expr中的return值(收益)
    hold_days = 5

    # 特征 https://bigquant.com/docs/data_features.html,你可以通过表达式构造任何特征
    features = [
        'return_40',  # 40日收益
        '(volume_0+volume_1+volume_2+volume_3+volume_4+volume_5+volume_6+volume_7+volume_8+volume_9)/10',  # 10日平均交易量
        'market_cap_float_0',  # 流通市值
        'pe_ttm_0',  # 市盈率TTM
        'mf_net_amount_10',  # 10日净主动买入额
        'fs_deducted_profit_ttm_0',  # 扣除经常性损益后净利润TTM
        'rank_fs_operating_revenue_qoq_0',  # 营业收入单季度环比增长率排名
        '(fs_current_liabilities_0+fs_non_current_liabilities_0)/(fs_current_assets_0+fs_non_current_assets_0)',  # 资产负债率
        'ta_sma_10_0',  # 10日移动平均
        'list_board_0',  # 上市板
    ]

# 给数据做标注:给每一行数据(样本)打分,一般分数越高表示越好
m1 = M.fast_auto_labeler.v5(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.end_date,
    label_expr=conf.label_expr, hold_days=conf.hold_days,
    benchmark='000300.SHA', sell_at='open', buy_at='open')
# 计算特征数据
m2 = M.general_feature_extractor.v5(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.end_date,
    features=conf.features)
# 数据预处理:缺失数据处理,数据规范化,T.get_stock_ranker_default_transforms为StockRanker模型做数据预处理
m3 = M.transform.v2(
    data=m2.data, transforms=T.get_stock_ranker_default_transforms(),
    drop_null=True, astype='int32', except_columns=['date', 'instrument'],
    clip_lower=0, clip_upper=200000000)
# 合并标注和特征数据
m4 = M.join.v2(data1=m1.data, data2=m3.data, on=['date', 'instrument'], sort=True)

# 训练数据集
m5_training = M.filter.v2(data=m4.data, expr='date < "%s"' % conf.split_date)
# 评估数据集
m5_evaluation = M.filter.v2(data=m4.data, expr='"%s" <= date' % conf.split_date)
# StockRanker机器学习训练
m6 = M.stock_ranker_train.v2(training_ds=m5_training.data, features=conf.features)
# 对评估集做预测
m7 = M.stock_ranker_predict.v2(model_id=m6.model_id, data=m5_evaluation.data)


## 量化回测 https://bigquant.com/docs/strategy_backtest.html
# 回测引擎:初始化函数,只执行一次
def initialize(context):
    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
    context.ranker_prediction = context.options['ranker_prediction'].read_df()
    # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只
    stock_count = 5
    # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[0.339160, 0.213986, 0.169580, ..]
    context.stock_weights = T.norm([1 / math.log(i + 2) for i in range(0, stock_count)])
    # 设置每只股票占用的最大资金比例
    context.max_cash_per_instrument = 0.2

# 回测引擎:每日数据处理函数,每天执行一次
def handle_data(context, data):
    # 按日期过滤得到今日的预测数据
    ranker_prediction = context.ranker_prediction[context.ranker_prediction.date == data.current_dt.strftime('%Y-%m-%d')]

    # 1. 资金分配
    # 平均持仓时间是hold_days,每日都将买入股票,每日预期使用 1/hold_days 的资金
    # 实际操作中,会存在一定的买入误差,所以在前hold_days天,等量使用资金;之后,尽量使用剩余资金(这里设置最多用等量的1.5倍)
    is_staging = context.trading_day_index < context.options['hold_days'] # 是否在建仓期间(前 hold_days 天)
    cash_avg = context.portfolio.portfolio_value / context.options['hold_days']
    cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)
    cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)
    positions = {e.symbol: p.amount * p.last_sale_price         for e, p in context.perf_tracker.position_tracker.positions.items()}

    # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按StockRanker预测的排序末位淘汰
    if not is_staging and cash_for_sell > 0:
        equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}
        instruments = list(reversed(list(ranker_prediction.instrument[ranker_prediction.instrument.apply(
                lambda x: x in equities and not context.has_unfinished_sell_order(equities[x]))])))
        # print('rank order for sell %s' % instruments)
        for instrument in instruments:
            context.order_target(context.symbol(instrument), 0)
            cash_for_sell -= positions[instrument]
            if cash_for_sell <= 0:
                break

    # 3. 生成买入订单:按StockRanker预测的排序,买入前面的stock_count只股票
    buy_cash_weights = context.stock_weights
    buy_instruments = list(ranker_prediction.instrument[:len(buy_cash_weights)])
    max_cash_per_instrument = context.portfolio.portfolio_value * context.max_cash_per_instrument
    for i, instrument in enumerate(buy_instruments):
        cash = cash_for_buy * buy_cash_weights[i]
        if cash > max_cash_per_instrument - positions.get(instrument, 0):
            # 确保股票持仓量不会超过每次股票最大的占用资金量
            cash = max_cash_per_instrument - positions.get(instrument, 0)
        if cash > 0:
            context.order_value(context.symbol(instrument), cash)

# 调用回测引擎
m8 = M.backtest.v5(
    instruments=m7.instruments,
    start_date=m7.start_date,
    end_date=m7.end_date,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',       # 表示 开盘 时买入
    order_price_field_sell='close',     # 表示 收盘 前卖出
    capital_base=1000000,               # 初始资金
    benchmark='000300.SHA',             # 比较基准,不影响回测结果
    # 通过 options 参数传递预测数据和参数给回测引擎
    options={'ranker_prediction': m7.predictions, 'hold_days': conf.hold_days} 
)
[2017-04-06 05:31:06.439831] INFO: bigquant: fast_auto_labeler.v5 start ..
[2017-04-06 05:31:13.048097] INFO: fast_auto_labeler: load history data: 4024675 rows
[2017-04-06 05:31:14.075045] INFO: fast_auto_labeler: start labeling
[2017-04-06 05:32:42.751507] INFO: bigquant: fast_auto_labeler.v5 end [96.311656s].
[2017-04-06 05:32:42.768443] INFO: bigquant: general_feature_extractor.v5 start ..
[2017-04-06 05:33:11.763707] INFO: general_feature_extractor: year 2010, featurerows=431567
[2017-04-06 05:33:46.305245] INFO: general_feature_extractor: year 2011, featurerows=511455
[2017-04-06 05:34:12.502131] INFO: general_feature_extractor: year 2012, featurerows=565675
[2017-04-06 05:34:40.300108] INFO: general_feature_extractor: year 2013, featurerows=564168
[2017-04-06 05:35:20.715219] INFO: general_feature_extractor: year 2014, featurerows=569948
[2017-04-06 05:36:01.489820] INFO: general_feature_extractor: year 2015, featurerows=569698
[2017-04-06 05:36:50.123336] INFO: general_feature_extractor: year 2016, featurerows=641546
[2017-04-06 05:37:02.726870] INFO: general_feature_extractor: year 2017, featurerows=170618
[2017-04-06 05:37:02.767138] INFO: general_feature_extractor: total feature rows: 4024675
[2017-04-06 05:37:02.774550] INFO: bigquant: general_feature_extractor.v5 end [260.006106s].
[2017-04-06 05:37:02.790136] INFO: bigquant: transform.v2 start ..
[2017-04-06 05:37:06.649926] INFO: transform: transformed /y_2010, 401752/431567
[2017-04-06 05:37:10.825224] INFO: transform: transformed /y_2011, 482336/511455
[2017-04-06 05:37:15.591421] INFO: transform: transformed /y_2012, 543439/565675
[2017-04-06 05:37:20.174332] INFO: transform: transformed /y_2013, 553828/564168
[2017-04-06 05:37:24.305668] INFO: transform: transformed /y_2014, 554302/569948
[2017-04-06 05:37:28.636192] INFO: transform: transformed /y_2015, 545340/569698
[2017-04-06 05:37:33.041923] INFO: transform: transformed /y_2016, 594461/641546
[2017-04-06 05:37:36.092206] INFO: transform: transformed /y_2017, 157596/170618
[2017-04-06 05:37:36.118884] INFO: transform: transformed rows: 3833054/4024675
[2017-04-06 05:37:36.129476] INFO: bigquant: transform.v2 end [33.339309s].
[2017-04-06 05:37:36.140062] INFO: bigquant: join.v2 start ..
[2017-04-06 05:37:44.477139] INFO: filter: /y_2010, rows=401234/401752, timetaken=7.000479s
[2017-04-06 05:37:52.351854] INFO: filter: /y_2011, rows=481859/482336, timetaken=7.812137s
[2017-04-06 05:37:59.799045] INFO: filter: /y_2012, rows=542392/543439, timetaken=7.358683s
[2017-04-06 05:38:09.079797] INFO: filter: /y_2013, rows=552815/553828, timetaken=9.184478s
[2017-04-06 05:38:18.950576] INFO: filter: /y_2014, rows=552836/554302, timetaken=9.76124s
[2017-04-06 05:38:28.449399] INFO: filter: /y_2015, rows=538550/545340, timetaken=9.397212s
[2017-04-06 05:38:38.673809] INFO: filter: /y_2016, rows=592851/594461, timetaken=10.201155s
[2017-04-06 05:38:45.762173] INFO: filter: /y_2017, rows=140642/157596, timetaken=7.063113s
[2017-04-06 05:38:45.943897] INFO: filter: total result rows: 3803179
[2017-04-06 05:38:45.947453] INFO: bigquant: join.v2 end [69.807379s].
[2017-04-06 05:38:45.957301] INFO: bigquant: filter.v2 start ..
[2017-04-06 05:38:45.963005] INFO: filter: filter with expr date < "2015-01-01"
[2017-04-06 05:38:46.587970] INFO: filter: filter /y_2010, 401234/401234
[2017-04-06 05:38:47.077751] INFO: filter: filter /y_2011, 481859/481859
[2017-04-06 05:38:47.630544] INFO: filter: filter /y_2012, 542392/542392
[2017-04-06 05:38:48.411764] INFO: filter: filter /y_2013, 552815/552815
[2017-04-06 05:38:49.486352] INFO: filter: filter /y_2014, 552836/552836
[2017-04-06 05:38:49.843958] INFO: filter: filter /y_2015, 0/538550
[2017-04-06 05:38:50.161798] INFO: filter: filter /y_2016, 0/592851
[2017-04-06 05:38:50.255386] INFO: filter: filter /y_2017, 0/140642
[2017-04-06 05:38:50.298617] INFO: bigquant: filter.v2 end [4.341281s].
[2017-04-06 05:38:50.307269] INFO: bigquant: filter.v2 start ..
[2017-04-06 05:38:50.312133] INFO: filter: filter with expr "2015-01-01" <= date
[2017-04-06 05:38:50.647947] INFO: filter: filter /y_2010, 0/401234
[2017-04-06 05:38:50.913431] INFO: filter: filter /y_2011, 0/481859
[2017-04-06 05:38:51.101855] INFO: filter: filter /y_2012, 0/542392
[2017-04-06 05:38:51.325564] INFO: filter: filter /y_2013, 0/552815
[2017-04-06 05:38:51.546693] INFO: filter: filter /y_2014, 0/552836
[2017-04-06 05:38:52.282936] INFO: filter: filter /y_2015, 538550/538550
[2017-04-06 05:38:53.722164] INFO: filter: filter /y_2016, 592851/592851
[2017-04-06 05:38:53.912511] INFO: filter: filter /y_2017, 140642/140642
[2017-04-06 05:38:53.950617] INFO: bigquant: filter.v2 end [3.643291s].
[2017-04-06 05:38:54.021889] INFO: bigquant: stock_ranker_train.v2 start ..
[2017-04-06 05:38:59.341381] INFO: df2bin: prepare data: training ..
[2017-04-06 05:40:21.518193] INFO: stock_ranker_train: training: 2531136 rows
[2017-04-06 05:43:06.539852] INFO: bigquant: stock_ranker_train.v2 end [252.518014s].
[2017-04-06 05:43:06.558283] INFO: bigquant: stock_ranker_predict.v2 start ..
[2017-04-06 05:43:08.021100] INFO: df2bin: prepare data: prediction ..
[2017-04-06 05:43:50.020112] INFO: stock_ranker_predict: prediction: 1272043 rows
[2017-04-06 05:44:10.374260] INFO: bigquant: stock_ranker_predict.v2 end [63.815866s].
[2017-04-06 05:44:10.605304] INFO: bigquant: backtest.v5 start ..
[2017-04-06 05:44:19.708926] INFO: Loader:            date  instrument         open         high          low  \
0    2005-01-04  000300.SHA   994.768982   994.768982   980.658020   
1    2005-01-05  000300.SHA   981.577026   997.322998   979.877014   
2    2005-01-06  000300.SHA   993.330994   993.788025   980.330017   
3    2005-01-07  000300.SHA   983.044983   995.710999   979.812012   
4    2005-01-10  000300.SHA   983.760010   993.958984   979.789001   
5    2005-01-11  000300.SHA   994.189026   999.554016   991.091980   
6    2005-01-12  000300.SHA   996.651001   996.976013   989.257019   
7    2005-01-13  000300.SHA   996.078003   999.473022   992.695007   
8    2005-01-14  000300.SHA   996.617004  1006.463013   987.232971   
9    2005-01-17  000300.SHA   979.111023   981.525024   965.078003   
10   2005-01-18  000300.SHA   967.374023   974.872009   960.293030   
11   2005-01-19  000300.SHA   974.333008   974.333008   965.257996   
12   2005-01-20  000300.SHA   963.213013   963.213013   952.229980   
13   2005-01-21  000300.SHA   954.461975   984.273987   943.439026   
14   2005-01-24  000300.SHA  1001.854004  1001.854004   986.239014   
15   2005-01-25  000300.SHA   995.637024   997.950989   985.237000   
16   2005-01-26  000300.SHA   995.780029   999.473999   988.474976   
17   2005-01-27  000300.SHA   987.341980   987.702026   973.770996   
18   2005-01-28  000300.SHA   974.630981   975.624023   965.208984   
19   2005-01-31  000300.SHA   965.784973   965.784973   953.142029   
20   2005-02-01  000300.SHA   953.330017   965.476990   952.741028   
21   2005-02-02  000300.SHA   956.700989  1006.932007   956.700989   
22   2005-02-03  000300.SHA  1005.562988  1014.187012   992.155029   
23   2005-02-04  000300.SHA   992.250000  1021.025024   989.939026   
24   2005-02-16  000300.SHA  1023.323975  1033.248047  1018.487000   
25   2005-02-17  000300.SHA  1024.430054  1024.430054  1010.476013   
26   2005-02-18  000300.SHA  1020.122009  1021.198975  1005.630981   
27   2005-02-21  000300.SHA  1006.692993  1025.656006  1006.692993   
28   2005-02-22  000300.SHA  1026.837036  1048.677979  1024.526978   
29   2005-02-23  000300.SHA  1046.812012  1049.609009  1036.625000   
...         ...         ...          ...          ...          ...   
2945 2017-02-21  000300.SHA  3475.058350  3490.085449  3472.017090   
2946 2017-02-22  000300.SHA  3483.200684  3489.946045  3473.523926   
2947 2017-02-23  000300.SHA  3487.574463  3492.961670  3460.117920   
2948 2017-02-24  000300.SHA  3468.958740  3473.851807  3455.251465   
2949 2017-02-27  000300.SHA  3471.131836  3472.835693  3441.393799   
2950 2017-02-28  000300.SHA  3445.027344  3460.908936  3441.358887   
2951 2017-03-01  000300.SHA  3452.205811  3472.696289  3449.108887   
2952 2017-03-02  000300.SHA  3463.482910  3468.470947  3434.000977   
2953 2017-03-03  000300.SHA  3424.662598  3428.882324  3412.831299   
2954 2017-03-06  000300.SHA  3427.253418  3449.034180  3425.904053   
2955 2017-03-07  000300.SHA  3446.162842  3454.038574  3440.057373   
2956 2017-03-08  000300.SHA  3452.200684  3457.035156  3441.257568   
2957 2017-03-09  000300.SHA  3442.895264  3443.045410  3414.678223   
2958 2017-03-10  000300.SHA  3423.977539  3436.238770  3423.937012   
2959 2017-03-13  000300.SHA  3425.672363  3458.097900  3412.687988   
2960 2017-03-14  000300.SHA  3456.658447  3465.391602  3448.903320   
2961 2017-03-15  000300.SHA  3452.213867  3463.919189  3445.267578   
2962 2017-03-16  000300.SHA  3472.269287  3492.126709  3472.269287   
2963 2017-03-17  000300.SHA  3485.311279  3488.496826  3441.468506   
2964 2017-03-20  000300.SHA  3449.051514  3454.062988  3429.825439   
2965 2017-03-21  000300.SHA  3449.769531  3466.702637  3445.641602   
2966 2017-03-22  000300.SHA  3450.754395  3464.332764  3433.499512   
2967 2017-03-23  000300.SHA  3452.405518  3470.816406  3435.691162   
2968 2017-03-24  000300.SHA  3464.196533  3499.317871  3461.110840   
2969 2017-03-27  000300.SHA  3488.764648  3505.979004  3474.520508   
2970 2017-03-28  000300.SHA  3480.249023  3482.292236  3461.467773   
2971 2017-03-29  000300.SHA  3472.966553  3483.057129  3455.552979   
2972 2017-03-30  000300.SHA  3461.615967  3467.304932  3422.365967   
2973 2017-03-31  000300.SHA  3434.822266  3456.305176  3430.819580   
2974 2017-04-05  000300.SHA  3476.423096  3504.537842  3475.148682   

            close       volume        amount  
0      982.794006    741286894  4.431977e+09  
1      992.564026    711910898  4.529208e+09  
2      983.174011    628802905  3.921015e+09  
3      983.958008    729869409  4.737469e+09  
4      993.879028    579169799  3.762933e+09  
5      997.135010    584907998  3.704077e+09  
6      996.747986    501452509  3.093300e+09  
7      996.877014    604406584  3.842173e+09  
8      988.306030    729784238  4.162921e+09  
9      967.452026    728818876  4.249808e+09  
10     974.689026    731184782  4.117944e+09  
11     967.210022    633809119  3.427951e+09  
12     956.244995    772710670  4.399351e+09  
13     982.604004   1445005985  8.152086e+09  
14     998.132996   1435946161  8.360161e+09  
15     997.775024    986252911  6.157022e+09  
16     989.927979    766329017  4.719440e+09  
17     974.630981    694536497  4.094399e+09  
18     969.208984    574880738  3.280950e+09  
19     954.879028    678870643  3.863574e+09  
20     955.950989    743306676  4.275707e+09  
21    1006.913025   1705733857  1.020290e+10  
22     993.215027   1697453932  1.005731e+10  
23    1016.857971   1573621461  9.549871e+09  
24    1023.583984   1213129305  7.438168e+09  
25    1020.606018    896829766  5.513063e+09  
26    1006.054993    813993936  4.817732e+09  
27    1025.633057    988609416  6.052395e+09  
28    1046.744019   1793784230  1.092278e+10  
29    1043.943970   1869692971  1.123194e+10  
...           ...          ...           ...  
2945  3482.822998  11484200900  1.206754e+11  
2946  3489.756592  10281599400  1.092324e+11  
2947  3473.323486   9953633000  1.065559e+11  
2948  3473.851807   9553513300  9.987517e+10  
2949  3446.222900   9867216000  1.068309e+11  
2950  3452.810303   7521526000  8.197931e+10  
2951  3458.437500  10326035400  1.093178e+11  
2952  3435.096191   8989807700  9.787619e+10  
2953  3427.862793   8099465200  9.000962e+10  
2954  3446.483887   8307088200  9.517855e+10  
2955  3453.956543   8033472000  9.448382e+10  
2956  3448.731201   7958769000  8.912490e+10  
2957  3426.943848   8457038100  9.009005e+10  
2958  3427.891602   7001619900  8.216171e+10  
2959  3458.097900   9168412400  1.084891e+11  
2960  3456.693359   7707796300  9.531757e+10  
2961  3463.643555   7910495400  9.405626e+10  
2962  3481.506592  10633391300  1.246956e+11  
2963  3445.805176  10375556000  1.223689e+11  
2964  3449.612549   8873432200  1.037694e+11  
2965  3466.346680   8770785500  1.135282e+11  
2966  3450.050293  10493589400  1.238656e+11  
2967  3461.978271   9431806200  1.158138e+11  
2968  3489.599609  12564583300  1.417525e+11  
2969  3478.038574  10701537700  1.243880e+11  
2970  3469.809326   8419482000  9.749594e+10  
2971  3465.193359  10485170600  1.146635e+11  
2972  3436.758057  11637692200  1.220880e+11  
2973  3456.045410   9157749100  1.009849e+11  
2974  3503.893311  14339901700  1.607430e+11  

[2975 rows x 8 columns]
[2017-04-06 05:45:56.681616] INFO: Performance: Simulated 541 trading days out of 541.
[2017-04-06 05:45:56.683184] INFO: Performance: first open: 2015-01-05 14:30:00+00:00
[2017-04-06 05:45:56.685151] INFO: Performance: last close: 2017-03-23 19:00:00+00:00
[注意] 有 1 笔卖出是在多天内完成的。当日卖出股票超过了当日股票交易的2.5%会出现这种情况。
[2017-04-06 05:45:58.003853] INFO: bigquant: ir base: 0.25336687653316836
  • 收益率143.82%
  • 年化收益率51.46%
  • 基准收益率-2.03%
  • 阿尔法0.43
  • 贝塔0.76
  • 夏普比率3.39
  • 收益波动率33.67%
  • 信息比率4.71
  • 最大回撤31.26%
  • 盈/亏次数929/685
  • 盈/亏利润率+5.25%/-4.33%
[2017-04-06 05:45:59.069155] INFO: bigquant: backtest.v5 end [108.463751s].

(神龙斗士) #2

加油 :grinning: