如何以年线以上的票为股票池


(skura69) #1

这个策略想以年线以上的票为股票池,如何添加这个条件呢

策略如下:

# 基础参数配置
class conf:
    start_date = '2017-01-01'
    end_date='2018-04-23'
    # split_date 之前的数据用于训练,之后的数据用作效果评估
    split_date = '2017-12-1'
    # D.instruments: https://bigquant.com/docs/data_instruments.html
    instruments = D.instruments(start_date, split_date)

    # 机器学习目标标注函数
    # 如下标注函数等价于 min(max((持有期间的收益 * 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 = 2

    # 特征 https://bigquant.com/docs/data_features.html,你可以通过表达式构造任何特征
    features = [
        'return_90/return_10',
        'return_30/return_10',
        'rank_return_20',
        'avg_turn_15/turn_0',
        'ta_sma_10_0/ta_sma_30_0',
        'return_2',
        '(high_0-low_0+high_1-low_1+high_2-low_2+high_3-low_3+high_4-low_4+high_5-low_5+high_6-low_6+high_7-low_7+high_8-low_8)',
    ]
    # st_status_0: https://bigquant.com/docs/data_features.html#id4
    extra_fields = ['st_status_0']

      
# 给数据做标注:给每一行数据(样本)打分,一般分数越高表示越好
m1 = M.fast_auto_labeler.v8(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.split_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.v6(
    instruments=conf.instruments,
    features=conf.features + conf.extra_fields,
    start_date=conf.start_date,
    end_date=conf.split_date,
    before_start_days=60
)
# 数据预处理:缺失数据处理,数据规范化,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)
# 从训练数据里去掉ST等股票,只保留正常状态的股票
m4_1 = M.filter.v2(data=m4.data, expr='st_status_0 == 0')
# StockRanker机器学习训练
m5 = M.stock_ranker_train.v3(training_ds=m4_1.data, features=conf.features)


## 量化回测 https://bigquant.com/docs/module_trade.html
# 回测引擎:准备数据,只执行一次
def prepare(context):
    # context.start_date / end_date,回测的时候,为trader传入参数;在实盘运行的时候,由系统替换为实盘日期
    n1 = M.general_feature_extractor.v5(
        instruments=D.instruments(start_date=context.start_date, end_date=context.end_date),
        start_date=context.start_date, end_date=context.end_date,
        model_id=context.options['model_id'],
        features=context.options['extra_fields'])
    n2 = M.transform.v2(
        data=n1.data, transforms=T.get_stock_ranker_default_transforms(),
        drop_null=True, astype='int32', except_columns=['date', 'instrument'],
        clip_lower=0, clip_upper=200000000)
    # 从训练数据里去掉ST等股票,只保留正常状态的股票
    n2_1 = M.filter.v2(data=n2.data, expr='st_status_0 == 0')
    n3 = M.stock_ranker_predict.v2(model_id=context.options['model_id'], data=n2_1.data)
    context.instruments = n3.instruments
    context.options['predictions'] = n3.predictions

# 回测引擎:初始化函数,只执行一次
def initialize(context):
    # 加载预测数据
    context.ranker_prediction = context.options['predictions'].read_df()

    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
    # 设置买入的股票数量,这里买入预测股票列表排名靠前的2只
    stock_count = 4
    # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[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 = 1.5

# 回测引擎:每日数据处理函数,每天执行一次
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) * 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:
            current_price = data.current(context.symbol(instrument), 'price')
            amount = math.floor(cash / current_price - cash / current_price % 100) 
            context.order(context.symbol(instrument), amount)


# 调用交易引擎
m6 = M.trade.v2(
    instruments=None,
    start_date=conf.split_date,
    end_date=conf.end_date,
    prepare=prepare,
    initialize=initialize,
    handle_data=handle_data,
    order_price_field_buy='open',       # 表示 开盘 时买入
    order_price_field_sell='close',     # 表示 收盘 前卖出
    capital_base=150000,               # 初始资金
#    price_type='real',
    benchmark='000300.SHA',             # 比较基准,不影响回测结果
    # 通过 options 参数传递预测数据和参数给回测引擎
    options={'hold_days': conf.hold_days, 'model_id': m5.model_id, 'extra_fields': conf.extra_fields}
)

(iQuant) #2

您好 您这个问题很典型
https://community.bigquant.com/t/可视化模板自定义指标过滤的实现/9092


(skura69) #3

万分感谢!


(skura69) #4

这个参考案例对于编程白痴还是太难了,研究了一天也没看懂,还是不知道如何以均线来过滤股票池,能否给一个以均线为参数过滤股票池的案例,谢谢


(iQuant) #5

首先,新建一个AI可视化策略模板,然后拖拽模块成为下图的样子
23bc7f08beb711a58b105fbf6210a77cb17a699e_1_690x466

然后您克隆一下策略,查看一下m15模块其实就是自定义了一个函数self_diy(close_0),self_diy可以理解为条件指标的名字,括号里是自变量close_0,因为计算这个条件指标需要收盘价。在自定义指标计算中(也就是衍生数据抽取中),我们定义了函数的具体计算内容:

import talib #这是引入一个计算技术指标的库,可以查一下论坛 基本能满足你的常用技术指标定义需求
def self_diy(df,close_0): 
    close = [float(x) for x in df['close_0']]
    df['condition']=(df['close_0']>talib.MA(np.array(close), timeperiod=5)).astype(int)
    return df['condition']
#上面这几句是定义你的自定义函数具体计算内容,也就是指标值condition,这里计算的是当收盘价>5日均线时就是1,否则就是0
m5_user_functions_bigquant_run = {
    'self_diy':  self_diy
}
#函数返回值会传给self_diy这个列

然后通过一个自定义python模块对这个指标条件进行过滤,取出满足条件的股票数据扔给训练器训练,同样在测试集右支部分也要进行同样的指标过滤
如果您只是想实现在买卖操作阶段做一个指标过滤控制,而不是训练的时候就考虑利用指标对标的进行过滤,您可以采用下面的方案,只是在trade回测模块中买入前进行一个过滤,可以参考 可视化模板自定义指标过滤的实现 帖子中增加了这个案例。


(skura69) #6

先谢谢不辞辛苦两次回复,然而我还是没搞明白,我以你给的例子修改了一个,把案例里面的5日线改成了60日线,结果不起作用,选出来依然有很多票是60日线以下的,帮忙看看是怎么回事?

代码如下:

# 本代码由可视化策略环境自动生成 2018年5月10日 17:43
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。


m1 = M.instruments.v2(
    start_date='2016-05-01',
    end_date='2018-05-05',
    market='CN_STOCK_A',
    instrument_list='',
    max_count=0
)

m2 = M.advanced_auto_labeler.v2(
    instruments=m1.data,
    label_expr="""# #号开始的表示注释
# 0. 每行一个,顺序执行,从第二个开始,可以使用label字段
# 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html
#   添加benchmark_前缀,可使用对应的benchmark数据
# 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_

# 计算收益:3日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
shift(close, -3) / shift(open, -1)

# 极值处理:用1%和99%分位的值做clip
clip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))

# 将分数映射到分类,这里使用20个分类
all_wbins(label, 20)

# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
where(shift(high, -1) == shift(low, -1), NaN, label)
""",
    start_date='',
    end_date='',
    benchmark='000300.SHA',
    drop_na_label=True,
    cast_label_int=True
)

m3 = M.input_features.v1(
    features="""# #号开始的表示注释
# 多个特征,每行一个,可以包含基础特征和衍生特征
return_90/return_10
return_30/return_10
rank_return_20
avg_turn_15/turn_0
return_2
turn_2
close_0""",
    m_cached=False
)

m15 = M.input_features.v1(
    features_ds=m3.data,
    features="""
# #号开始的表示注释
# 多个特征,每行一个,可以包含基础特征和衍生特征
self_diy(close_0)""",
    m_cached=False
)

m4 = M.general_feature_extractor.v6(
    instruments=m1.data,
    features=m15.data,
    start_date='',
    end_date='',
    before_start_days=300
)

import talib
def self_diy(df,close_0): 
    close = [float(x) for x in df['close_0']]
    df['close_0']=(df['close_0']>talib.MA(np.array(close), timeperiod=5)).astype(int)
    return df['close_0']
   #return pd.rolling_apply(df['close_0'], 60,np.mean)
m5_user_functions_bigquant_run = {
    'self_diy':  self_diy
}

m5 = M.derived_feature_extractor.v2(
    input_data=m4.data,
    features=m15.data,
    date_col='date',
    instrument_col='instrument',
    user_functions=m5_user_functions_bigquant_run,
    m_cached=False
)

# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m16_run_bigquant_run(input_1, input_2, input_3):
    # 示例代码如下。在这里编写您的代码
    df = input_1.read_df()
    df1=df[df['self_diy(close_0)']>0]
    data_1 = DataSource.write_df(df1)
    return Outputs(data_1=data_1, data_2=None, data_3=None)

m16 = M.cached.v3(
    input_1=m5.data,
    run=m16_run_bigquant_run
)

m7 = M.join.v3(
    data1=m2.data,
    data2=m16.data_1,
    on='date,instrument',
    how='inner',
    sort=False
)

m13 = M.dropnan.v1(
    input_data=m7.data
)

m6 = M.stock_ranker_train.v5(
    training_ds=m13.data,
    features=m3.data,
    learning_algorithm='排序',
    number_of_leaves=30,
    minimum_docs_per_leaf=1000,
    number_of_trees=20,
    learning_rate=0.1,
    max_bins=1023,
    feature_fraction=1,
    m_lazy_run=False
)

m9 = M.instruments.v2(
    start_date=T.live_run_param('trading_date', '2017-10-01'),
    end_date=T.live_run_param('trading_date', '2018-05-05'),
    market='CN_STOCK_A',
    instrument_list='',
    max_count=0
)

m10 = M.general_feature_extractor.v6(
    instruments=m9.data,
    features=m3.data,
    start_date='',
    end_date='',
    before_start_days=0
)

import talib
def self_diy(df,close_0): 
    close = [float(x) for x in df['close_0']]
    df['close_0']=(df['close_0']>talib.MA(np.array(close), timeperiod=5)).astype(int)
    return df['close_0']
   #return pd.rolling_apply(df['close_0'], 60,np.mean)
m11_user_functions_bigquant_run = {
    'self_diy':  self_diy
}

m11 = M.derived_feature_extractor.v2(
    input_data=m10.data,
    features=m15.data,
    date_col='date',
    instrument_col='instrument',
    user_functions=m11_user_functions_bigquant_run
)

# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m17_run_bigquant_run(input_1, input_2, input_3):
    # 示例代码如下。在这里编写您的代码
    df = input_1.read_df()
    df1=df[df['self_diy(close_0)']>0]
    data_1 = DataSource.write_df(df1)
    return Outputs(data_1=data_1, data_2=None, data_3=None)

m17 = M.cached.v3(
    input_1=m11.data,
    run=m17_run_bigquant_run
)

m14 = M.dropnan.v1(
    input_data=m17.data_1
)

m8 = M.stock_ranker_predict.v5(
    model=m6.model,
    data=m14.data,
    m_lazy_run=False
)

# 回测引擎:每日数据处理函数,每天执行一次
def m12_handle_data_bigquant_run(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天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰
    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. 生成买入订单:按机器学习算法预测的排序,买入前面的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)

# 回测引擎:准备数据,只执行一次
def m12_prepare_bigquant_run(context):
    pass

# 回测引擎:初始化函数,只执行一次
def m12_initialize_bigquant_run(context):
    # 加载预测数据
    context.ranker_prediction = context.options['data'].read_df()

    # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
    # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
    # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只
    stock_count = 2
    # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[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
    context.options['hold_days'] = 2

m12 = M.trade.v3(
    instruments=m9.data,
    options_data=m8.predictions,
    start_date='',
    end_date='',
    handle_data=m12_handle_data_bigquant_run,
    prepare=m12_prepare_bigquant_run,
    initialize=m12_initialize_bigquant_run,
    volume_limit=0.025,
    order_price_field_buy='open',
    order_price_field_sell='close',
    capital_base=500000,
    benchmark='000300.SHA',
    auto_cancel_non_tradable_orders=True,
    data_frequency='daily',
    price_type='后复权',
    plot_charts=True,
    backtest_only=False,
    amount_integer=False
)

(达达) #7

帖子里有两篇案例,如果您只是买股票的时候风控过滤一下请参考第一个案例,第一个案例中您只需要修改周期就好了

克隆策略

    {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data2","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:model","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:model"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81:options_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:predictions"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:data"},{"DestinationInputPortId":"-86:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:training_ds","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:data","SourceOutputPortId":"-86:data"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2012-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2015-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","ModuleId":"BigQuantSpace.advanced_auto_labeler.advanced_auto_labeler-v2","ModuleParameters":[{"Name":"label_expr","Value":"# #号开始的表示注释\n# 0. 每行一个,顺序执行,从第二个开始,可以使用label字段\n# 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html\n# 添加benchmark_前缀,可使用对应的benchmark数据\n# 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_\n\n# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)\nshift(close, -5) / shift(open, -1)\n\n# 极值处理:用1%和99%分位的值做clip\nclip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))\n\n# 将分数映射到分类,这里使用20个分类\nall_wbins(label, 20)\n\n# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)\nwhere(shift(high, -1) == shift(low, -1), NaN, label)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"000300.SHA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na_label","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"cast_label_int","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"# #号开始的表示注释\n# 多个特征,每行一个,可以包含基础特征和衍生特征\nclose_0\nreturn_5/return_10","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":3,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-29","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v6","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":"300","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":4,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-35","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v2","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"{}","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":5,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","ModuleId":"BigQuantSpace.stock_ranker_train.stock_ranker_train-v5","ModuleParameters":[{"Name":"learning_algorithm","Value":"排序","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"number_of_leaves","Value":30,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"minimum_docs_per_leaf","Value":1000,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"number_of_trees","Value":20,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"learning_rate","Value":0.1,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_bins","Value":1023,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"feature_fraction","Value":1,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"m_lazy_run","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"training_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"test_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"base_model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"}],"OutputPortsInternal":[{"Name":"model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null},{"Name":"feature_gains","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null},{"Name":"m_lazy_run","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":6,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":7,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","ModuleId":"BigQuantSpace.stock_ranker_predict.stock_ranker_predict-v5","ModuleParameters":[{"Name":"m_lazy_run","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60"}],"OutputPortsInternal":[{"Name":"predictions","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","OutputType":null},{"Name":"m_lazy_run","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":8,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2015-01-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"end_date","Value":"2015-03-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":9,"IsPartOfPartialRun":null,"Comment":"预测数据,用于回测和模拟","CommentCollapsed":false},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-70","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v6","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":"300","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":10,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-76","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v2","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"import talib\ndef self_diy(df,close_0): \n close = [float(x) for x in df['close_0']]\n df['close_0']=(df['close_0']>talib.MA(np.array(close), timeperiod=5)).astype(int)\n return df['close_0']\n #return pd.rolling_apply(df['close_0'], 5,np.mean)\nbigquant_run = {\n 'self_diy': self_diy\n}\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":11,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-81","ModuleId":"BigQuantSpace.trade.trade-v3","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n # 按日期过滤得到今日的预测数据\n ranker_prediction = context.ranker_prediction[\n context.ranker_prediction.date == data.current_dt.strftime('%Y-%m-%d')]\n\n # 1. 资金分配\n # 平均持仓时间是hold_days,每日都将买入股票,每日预期使用 1/hold_days 的资金\n # 实际操作中,会存在一定的买入误差,所以在前hold_days天,等量使用资金;之后,尽量使用剩余资金(这里设置最多用等量的1.5倍)\n is_staging = context.trading_day_index < context.options['hold_days'] # 是否在建仓期间(前 hold_days 天)\n cash_avg = context.portfolio.portfolio_value / context.options['hold_days']\n cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)\n cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)\n positions = {e.symbol: p.amount * p.last_sale_price\n for e, p in context.perf_tracker.position_tracker.positions.items()}\n\n # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰\n if not is_staging and cash_for_sell > 0:\n equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}\n instruments = list(reversed(list(ranker_prediction.instrument[ranker_prediction.instrument.apply(\n lambda x: x in equities and not context.has_unfinished_sell_order(equities[x]))])))\n # print('rank order for sell %s' % instruments)\n for instrument in instruments:\n context.order_target(context.symbol(instrument), 0)\n cash_for_sell -= positions[instrument]\n if cash_for_sell <= 0:\n break\n\n # 3. 生成买入订单:按机器学习算法预测的排序,买入前面的stock_count只股票\n buy_cash_weights = context.stock_weights\n buy_condition=context.buy_condition\n buy_list_today=list(buy_condition[(buy_condition['date']==data.current_dt.strftime('%Y-%m-%d')) & (buy_condition.condition>0)].instrument)\n all_instruments = list(ranker_prediction.instrument)\n buy_list=[i for i in all_instruments if i in buy_list_today]\n buy_instruments=buy_list[:len(buy_cash_weights)]\n max_cash_per_instrument = context.portfolio.portfolio_value * context.max_cash_per_instrument\n for i, instrument in enumerate(buy_instruments):\n cash = cash_for_buy * buy_cash_weights[i]\n if cash > max_cash_per_instrument - positions.get(instrument, 0):\n # 确保股票持仓量不会超过每次股票最大的占用资金量\n cash = max_cash_per_instrument - positions.get(instrument, 0)\n if cash > 0:\n context.order_value(context.symbol(instrument), cash)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n pass\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n # 加载预测数据\n context.ranker_prediction = context.options['data'].read_df()\n \n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))\n # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)\n # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只\n stock_count = 5\n # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[0.339160, 0.213986, 0.169580, ..]\n context.stock_weights = T.norm([1 / math.log(i + 2) for i in range(0, stock_count)])\n # 设置每只股票占用的最大资金比例\n context.max_cash_per_instrument = 0.2\n context.options['hold_days'] = 5\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"def bigquant_run(context,data):\n end_date=context.end_date\n start_date=(pd.to_datetime(context.end_date) - datetime.timedelta(days=200)).strftime('%Y-%m-%d') # 多取几天的数据\n all_data = D.history_data(context.instruments, start_date=start_date , end_date=end_date, fields=['close']).reset_index()\n all_data['ma_60'] = all_data['close'].rolling(60).mean()\n all_data['self_func'] = all_data['ma_60'] < all_data['close']\n all_data['condition'] = np.where(all_data['self_func'],1,0) \n buy_condition = all_data[['date','instrument','condition']]\n #这里根据自定义条件确定一个买入条件\n context.buy_condition=buy_condition\n #通过context把计算的每日仓位数据pos_df传给handle,信号以当日价格计算,次日执行","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"volume_limit","Value":0.025,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_buy","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_sell","Value":"close","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"capital_base","Value":"1000001","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"000300.SHA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"auto_cancel_non_tradable_orders","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"data_frequency","Value":"daily","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"price_type","Value":"后复权","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"plot_charts","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"backtest_only","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"amount_integer","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":12,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":13,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true},{"Id":"-86","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-86"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-86","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":14,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true}],"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-8' Position='211,64,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-15' Position='70,183,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='671,23,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-29' Position='381,188,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-35' Position='372,265,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-43' Position='638,561,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-53' Position='237,406,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-60' Position='906,647,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-62' Position='1074,127,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-70' Position='1078,236,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-76' Position='1074,315,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-81' Position='1038,752,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-84' Position='408,504,200,200'/><NodePosition Node='-86' Position='1069,467,200,200'/></NodePositions><NodeGroups /></DataV1>"},"IsDraft":true,"ParentExperimentId":null,"WebService":{"IsWebServiceExperiment":false,"Inputs":[],"Outputs":[],"Parameters":[{"Name":"交易日期","Value":"","ParameterDefinition":{"Name":"交易日期","FriendlyName":"交易日期","DefaultValue":"","ParameterType":"String","HasDefaultValue":true,"IsOptional":true,"ParameterRules":[],"HasRules":false,"MarkupType":0,"CredentialDescriptor":null}}],"WebServiceGroupId":null,"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions></NodePositions><NodeGroups /></DataV1>"},"DisableNodesUpdate":false,"Category":"user","Tags":[],"IsPartialRun":true}
    In [7]:
    # 本代码由可视化策略环境自动生成 2018年5月10日 18:49
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    m1 = M.instruments.v2(
        start_date='2012-01-01',
        end_date='2015-01-01',
        market='CN_STOCK_A',
        instrument_list='',
        max_count=0
    )
    
    m2 = M.advanced_auto_labeler.v2(
        instruments=m1.data,
        label_expr="""# #号开始的表示注释
    # 0. 每行一个,顺序执行,从第二个开始,可以使用label字段
    # 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html
    #   添加benchmark_前缀,可使用对应的benchmark数据
    # 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_
    
    # 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
    shift(close, -5) / shift(open, -1)
    
    # 极值处理:用1%和99%分位的值做clip
    clip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))
    
    # 将分数映射到分类,这里使用20个分类
    all_wbins(label, 20)
    
    # 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
    where(shift(high, -1) == shift(low, -1), NaN, label)
    """,
        start_date='',
        end_date='',
        benchmark='000300.SHA',
        drop_na_label=True,
        cast_label_int=True
    )
    
    m3 = M.input_features.v1(
        features="""# #号开始的表示注释
    # 多个特征,每行一个,可以包含基础特征和衍生特征
    close_0
    return_5/return_10"""
    )
    
    m4 = M.general_feature_extractor.v6(
        instruments=m1.data,
        features=m3.data,
        start_date='',
        end_date='',
        before_start_days=300
    )
    
    m5 = M.derived_feature_extractor.v2(
        input_data=m4.data,
        features=m3.data,
        date_col='date',
        instrument_col='instrument',
        user_functions={}
    )
    
    m7 = M.join.v3(
        data1=m2.data,
        data2=m5.data,
        on='date,instrument',
        how='inner',
        sort=False
    )
    
    m13 = M.dropnan.v1(
        input_data=m7.data
    )
    
    m6 = M.stock_ranker_train.v5(
        training_ds=m13.data,
        features=m3.data,
        learning_algorithm='排序',
        number_of_leaves=30,
        minimum_docs_per_leaf=1000,
        number_of_trees=20,
        learning_rate=0.1,
        max_bins=1023,
        feature_fraction=1,
        m_lazy_run=False
    )
    
    m9 = M.instruments.v2(
        start_date=T.live_run_param('trading_date', '2015-01-01'),
        end_date=T.live_run_param('trading_date', '2015-03-01'),
        market='CN_STOCK_A',
        instrument_list='',
        max_count=0
    )
    
    m10 = M.general_feature_extractor.v6(
        instruments=m9.data,
        features=m3.data,
        start_date='',
        end_date='',
        before_start_days=300
    )
    
    import talib
    def self_diy(df,close_0): 
        close = [float(x) for x in df['close_0']]
        df['close_0']=(df['close_0']>talib.MA(np.array(close), timeperiod=5)).astype(int)
        return df['close_0']
       #return pd.rolling_apply(df['close_0'], 5,np.mean)
    m11_user_functions_bigquant_run = {
        'self_diy':  self_diy
    }
    
    m11 = M.derived_feature_extractor.v2(
        input_data=m10.data,
        features=m3.data,
        date_col='date',
        instrument_col='instrument',
        user_functions=m11_user_functions_bigquant_run
    )
    
    m14 = M.dropnan.v1(
        input_data=m11.data
    )
    
    m8 = M.stock_ranker_predict.v5(
        model=m6.model,
        data=m14.data,
        m_lazy_run=False
    )
    
    # 回测引擎:每日数据处理函数,每天执行一次
    def m12_handle_data_bigquant_run(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天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰
        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. 生成买入订单:按机器学习算法预测的排序,买入前面的stock_count只股票
        buy_cash_weights = context.stock_weights
        buy_condition=context.buy_condition
        buy_list_today=list(buy_condition[(buy_condition['date']==data.current_dt.strftime('%Y-%m-%d')) & (buy_condition.condition>0)].instrument)
        all_instruments = list(ranker_prediction.instrument)
        buy_list=[i for i in all_instruments if i in buy_list_today]
        buy_instruments=buy_list[: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)
    
    # 回测引擎:准备数据,只执行一次
    def m12_prepare_bigquant_run(context):
        pass
    
    # 回测引擎:初始化函数,只执行一次
    def m12_initialize_bigquant_run(context):
        # 加载预测数据
        context.ranker_prediction = context.options['data'].read_df()
        
        # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
        # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
        # 设置买入的股票数量,这里买入预测股票列表排名靠前的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
        context.options['hold_days'] = 5
    
    def m12_before_trading_start_bigquant_run(context,data):
        end_date=context.end_date
        start_date=(pd.to_datetime(context.end_date) - datetime.timedelta(days=200)).strftime('%Y-%m-%d') # 多取几天的数据
        all_data = D.history_data(context.instruments, start_date=start_date , end_date=end_date, fields=['close']).reset_index()
        all_data['ma_60'] = all_data['close'].rolling(60).mean()
        all_data['self_func'] = all_data['ma_60'] < all_data['close']
        all_data['condition'] = np.where(all_data['self_func'],1,0)     
        buy_condition = all_data[['date','instrument','condition']]
        #这里根据自定义条件确定一个买入条件
        context.buy_condition=buy_condition
        #通过context把计算的每日仓位数据pos_df传给handle,信号以当日价格计算,次日执行
    m12 = M.trade.v3(
        instruments=m9.data,
        options_data=m8.predictions,
        start_date='',
        end_date='',
        handle_data=m12_handle_data_bigquant_run,
        prepare=m12_prepare_bigquant_run,
        initialize=m12_initialize_bigquant_run,
        before_trading_start=m12_before_trading_start_bigquant_run,
        volume_limit=0.025,
        order_price_field_buy='open',
        order_price_field_sell='close',
        capital_base=1000001,
        benchmark='000300.SHA',
        auto_cancel_non_tradable_orders=True,
        data_frequency='daily',
        price_type='后复权',
        plot_charts=True,
        backtest_only=False,
        amount_integer=False
    )
    
    [2018-05-10 18:16:43.091239] INFO: bigquant: instruments.v2 开始运行..
    [2018-05-10 18:16:43.096071] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.097730] INFO: bigquant: instruments.v2 运行完成[0.006538s].
    [2018-05-10 18:16:43.110420] INFO: bigquant: advanced_auto_labeler.v2 开始运行..
    [2018-05-10 18:16:43.114184] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.116110] INFO: bigquant: advanced_auto_labeler.v2 运行完成[0.005698s].
    [2018-05-10 18:16:43.128853] INFO: bigquant: input_features.v1 开始运行..
    [2018-05-10 18:16:43.132867] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.134315] INFO: bigquant: input_features.v1 运行完成[0.005473s].
    [2018-05-10 18:16:43.161533] INFO: bigquant: general_feature_extractor.v6 开始运行..
    [2018-05-10 18:16:43.165273] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.166542] INFO: bigquant: general_feature_extractor.v6 运行完成[0.005033s].
    [2018-05-10 18:16:43.185543] INFO: bigquant: derived_feature_extractor.v2 开始运行..
    [2018-05-10 18:16:43.194102] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.198474] INFO: bigquant: derived_feature_extractor.v2 运行完成[0.012928s].
    [2018-05-10 18:16:43.212660] INFO: bigquant: join.v3 开始运行..
    [2018-05-10 18:16:43.222101] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.225640] INFO: bigquant: join.v3 运行完成[0.012988s].
    [2018-05-10 18:16:43.237580] INFO: bigquant: dropnan.v1 开始运行..
    [2018-05-10 18:16:43.244699] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.246093] INFO: bigquant: dropnan.v1 运行完成[0.00854s].
    [2018-05-10 18:16:43.260677] INFO: bigquant: stock_ranker_train.v5 开始运行..
    [2018-05-10 18:16:43.274743] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.276090] INFO: bigquant: stock_ranker_train.v5 运行完成[0.015453s].
    [2018-05-10 18:16:43.287734] INFO: bigquant: instruments.v2 开始运行..
    [2018-05-10 18:16:43.291604] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.295361] INFO: bigquant: instruments.v2 运行完成[0.007622s].
    [2018-05-10 18:16:43.316302] INFO: bigquant: general_feature_extractor.v6 开始运行..
    [2018-05-10 18:16:43.332507] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.335154] INFO: bigquant: general_feature_extractor.v6 运行完成[0.018854s].
    [2018-05-10 18:16:43.349516] INFO: bigquant: derived_feature_extractor.v2 开始运行..
    [2018-05-10 18:16:43.353517] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.354578] INFO: bigquant: derived_feature_extractor.v2 运行完成[0.005106s].
    [2018-05-10 18:16:43.371011] INFO: bigquant: dropnan.v1 开始运行..
    [2018-05-10 18:16:43.375246] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.377380] INFO: bigquant: dropnan.v1 运行完成[0.006387s].
    [2018-05-10 18:16:43.390760] INFO: bigquant: stock_ranker_predict.v5 开始运行..
    [2018-05-10 18:16:43.402859] INFO: bigquant: 命中缓存
    [2018-05-10 18:16:43.404317] INFO: bigquant: stock_ranker_predict.v5 运行完成[0.013565s].
    [2018-05-10 18:16:43.459559] INFO: bigquant: backtest.v7 开始运行..
    [2018-05-10 18:16:43.654762] INFO: algo: set price type:backward_adjusted
    [2018-05-10 18:17:42.975666] INFO: Performance: Simulated 35 trading days out of 35.
    [2018-05-10 18:17:42.978595] INFO: Performance: first open: 2015-01-05 01:30:00+00:00
    [2018-05-10 18:17:42.981262] INFO: Performance: last close: 2015-02-27 07:00:00+00:00
    
    • 收益率6.8%
    • 年化收益率60.61%
    • 基准收益率1.11%
    • 阿尔法0.54
    • 贝塔0.47
    • 夏普比率2.33
    • 胜率0.565
    • 盈亏比1.299
    • 收益波动率23.95%
    • 信息比率2.11
    • 最大回撤5.93%
    [2018-05-10 18:17:43.839026] INFO: bigquant: backtest.v7 运行完成[60.379468s].
    


    (小Q) #8

    其实很简单,加一个自定义模块和数据过滤模块就可以,模型预测出来以后,将年线以下的股票去除就是。

    克隆策略

      {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:features","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data2","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:model","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:model"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81:options_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:predictions"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81:instruments","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"-110:input_1","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70:data"},{"DestinationInputPortId":"-86:input_data","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43:training_ds","SourceOutputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84:data"},{"DestinationInputPortId":"-123:data2","SourceOutputPortId":"-86:data"},{"DestinationInputPortId":"-123:data1","SourceOutputPortId":"-110:data_1"},{"DestinationInputPortId":"-130:input_data","SourceOutputPortId":"-123:data"},{"DestinationInputPortId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60:data","SourceOutputPortId":"-130:data"}],"ModuleNodes":[{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2010-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2015-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-8","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":1,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","ModuleId":"BigQuantSpace.advanced_auto_labeler.advanced_auto_labeler-v2","ModuleParameters":[{"Name":"label_expr","Value":"# #号开始的表示注释\n# 0. 每行一个,顺序执行,从第二个开始,可以使用label字段\n# 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html\n# 添加benchmark_前缀,可使用对应的benchmark数据\n# 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_\n\n# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)\nshift(close, -5) / shift(open, -1)\n\n# 极值处理:用1%和99%分位的值做clip\nclip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))\n\n# 将分数映射到分类,这里使用20个分类\nall_wbins(label, 20)\n\n# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)\nwhere(shift(high, -1) == shift(low, -1), NaN, label)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"000300.SHA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"drop_na_label","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"cast_label_int","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-15","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":2,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","ModuleId":"BigQuantSpace.input_features.input_features-v1","ModuleParameters":[{"Name":"features","Value":"# #号开始的表示注释\n# 多个特征,每行一个,可以包含基础特征和衍生特征\nreturn_5\nreturn_10\nreturn_20\navg_amount_0/avg_amount_5\navg_amount_5/avg_amount_20\nrank_avg_amount_0/rank_avg_amount_5\nrank_avg_amount_5/rank_avg_amount_10\nrank_return_0\nrank_return_5\nrank_return_10\nrank_return_0/rank_return_5\nrank_return_5/rank_return_10\npe_ttm_0\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-24","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":3,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-29","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v6","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":0,"ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-29","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":4,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-35","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v2","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-35","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":5,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","ModuleId":"BigQuantSpace.stock_ranker_train.stock_ranker_train-v5","ModuleParameters":[{"Name":"learning_algorithm","Value":"排序","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"number_of_leaves","Value":30,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"minimum_docs_per_leaf","Value":1000,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"number_of_trees","Value":20,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"learning_rate","Value":0.1,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_bins","Value":1023,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"feature_fraction","Value":1,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"m_lazy_run","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"training_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"test_ds","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"base_model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43"}],"OutputPortsInternal":[{"Name":"model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null},{"Name":"feature_gains","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null},{"Name":"m_lazy_run","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-43","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":6,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-53","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":7,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","ModuleId":"BigQuantSpace.stock_ranker_predict.stock_ranker_predict-v5","ModuleParameters":[{"Name":"m_lazy_run","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"model","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60"}],"OutputPortsInternal":[{"Name":"predictions","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","OutputType":null},{"Name":"m_lazy_run","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-60","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":8,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","ModuleId":"BigQuantSpace.instruments.instruments-v2","ModuleParameters":[{"Name":"start_date","Value":"2015-01-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"end_date","Value":"2017-01-01","ValueType":"Literal","LinkedGlobalParameter":"交易日期"},{"Name":"market","Value":"CN_STOCK_A","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_list","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"max_count","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"rolling_conf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-62","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":9,"Comment":"预测数据,用于回测和模拟","CommentCollapsed":false},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-70","ModuleId":"BigQuantSpace.general_feature_extractor.general_feature_extractor-v6","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_start_days","Value":0,"ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-70","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":10,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-76","ModuleId":"BigQuantSpace.derived_feature_extractor.derived_feature_extractor-v2","ModuleParameters":[{"Name":"date_col","Value":"date","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"instrument_col","Value":"instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"user_functions","Value":"","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"features","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-76","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":11,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-81","ModuleId":"BigQuantSpace.trade.trade-v3","ModuleParameters":[{"Name":"start_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"handle_data","Value":"# 回测引擎:每日数据处理函数,每天执行一次\ndef bigquant_run(context, data):\n \n date = data.current_dt.strftime('%Y-%m-%d')\n #------------------------------------------止损模块START--------------------------------------------\n positions = {e.symbol: p.cost_basis for e, p in context.portfolio.positions.items()}\n # 新建当日止损股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断\n current_stoploss_stock = [] # 将当天止损的股票整理到一个集合\n if len(positions) > 0:\n for i in positions.keys():\n stock_cost = positions[i] \n stock_market_price = data.current(context.symbol(i), 'price') \n # 亏5%就止损\n if (stock_market_price - stock_cost) / stock_cost <= -0.05: \n context.order_target_percent(context.symbol(i),0) \n current_stoploss_stock.append(i)\n # print('日期:',date,'股票:',i,'出现止损状况')\n #-------------------------------------------止损模块END---------------------------------------------\n \n #------------------------------------------止赢模块START--------------------------------------------\n # 新建当日止赢股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断\n current_stopwin_stock = [] # 将当天止盈的股票整理到一个集合\n if len(positions) > 0:\n for i in positions.keys():\n stock_cost = positions[i] \n stock_market_price = data.current(context.symbol(i), 'price') \n # 赚10%就止赢\n if (stock_market_price - stock_cost ) / stock_cost>= 0.1: \n context.order_target_percent(context.symbol(i),0) \n current_stopwin_stock.append(i)\n # print('日期:',date,'股票:',i,'出现止盈状况')\n #-------------------------------------------止赢模块END---------------------------------------------\n \n \n \n # 按日期过滤得到今日的预测数据\n ranker_prediction = context.ranker_prediction[\n context.ranker_prediction.date == data.current_dt.strftime('%Y-%m-%d')]\n\n # 1. 资金分配\n # 平均持仓时间是hold_days,每日都将买入股票,每日预期使用 1/hold_days 的资金\n # 实际操作中,会存在一定的买入误差,所以在前hold_days天,等量使用资金;之后,尽量使用剩余资金(这里设置最多用等量的1.5倍)\n is_staging = context.trading_day_index < context.options['hold_days'] # 是否在建仓期间(前 hold_days 天)\n cash_avg = context.portfolio.portfolio_value / context.options['hold_days']\n cash_for_buy = min(context.portfolio.cash, (1 if is_staging else 1.5) * cash_avg)\n cash_for_sell = cash_avg - (context.portfolio.cash - cash_for_buy)\n positions = {e.symbol: p.amount * p.last_sale_price\n for e, p in context.portfolio.positions.items()}\n\n # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰\n if not is_staging and cash_for_sell > 0:\n equities = {e.symbol: e for e, p in context.perf_tracker.position_tracker.positions.items()}\n instruments = list(reversed(list(ranker_prediction.instrument[ranker_prediction.instrument.apply(\n lambda x: x in equities and not context.has_unfinished_sell_order(equities[x]))])))\n # print('rank order for sell %s' % instruments)\n for instrument in instruments:\n if (instrument not in current_stopwin_stock) and (instrument not in current_stoploss_stock):\n context.order_target(context.symbol(instrument), 0)\n cash_for_sell -= positions[instrument]\n if cash_for_sell <= 0:\n break\n\n # 3. 生成买入订单:按机器学习算法预测的排序,买入前面的stock_count只股票\n buy_cash_weights = context.stock_weights\n buy_instruments = list(ranker_prediction.instrument[:len(buy_cash_weights)])\n max_cash_per_instrument = context.portfolio.portfolio_value * context.max_cash_per_instrument\n for i, instrument in enumerate(buy_instruments):\n cash = cash_for_buy * buy_cash_weights[i]\n if cash > max_cash_per_instrument - positions.get(instrument, 0):\n # 确保股票持仓量不会超过每次股票最大的占用资金量\n cash = max_cash_per_instrument - positions.get(instrument, 0)\n if cash > 0 and (instrument not in current_stopwin_stock) and (instrument not in current_stoploss_stock):\n context.order_value(context.symbol(instrument), cash)\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"prepare","Value":"# 回测引擎:准备数据,只执行一次\ndef bigquant_run(context):\n pass\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"initialize","Value":"# 回测引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n # 加载预测数据\n context.ranker_prediction = context.options['data'].read_df()\n\n # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数\n context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))\n # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)\n # 设置买入的股票数量,这里买入预测股票列表排名靠前的5只\n stock_count = 5\n # 每只的股票的权重,如下的权重分配会使得靠前的股票分配多一点的资金,[0.339160, 0.213986, 0.169580, ..]\n context.stock_weights = T.norm([1 / math.log(i + 2) for i in range(0, stock_count)])\n # 设置每只股票占用的最大资金比例\n context.max_cash_per_instrument = 0.2\n context.options['hold_days'] = 5\n","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"before_trading_start","Value":"","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"volume_limit","Value":"0","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_buy","Value":"open","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"order_price_field_sell","Value":"close","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"capital_base","Value":1000000,"ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"benchmark","Value":"000300.SHA","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"auto_cancel_non_tradable_orders","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"data_frequency","Value":"daily","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"price_type","Value":"后复权","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"plot_charts","Value":"True","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"backtest_only","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"amount_integer","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"instruments","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"options_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81"}],"OutputPortsInternal":[{"Name":"raw_perf","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-81","OutputType":null}],"UsePreviousResults":false,"moduleIdForCode":12,"Comment":"","CommentCollapsed":true},{"Id":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84"}],"OutputPortsInternal":[{"Name":"data","NodeId":"287d2cb0-f53c-4101-bdf8-104b137c8601-84","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":13,"Comment":"","CommentCollapsed":true},{"Id":"-86","ModuleId":"BigQuantSpace.dropnan.dropnan-v1","ModuleParameters":[],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-86"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-86","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":14,"Comment":"","CommentCollapsed":true},{"Id":"-110","ModuleId":"BigQuantSpace.cached.cached-v3","ModuleParameters":[{"Name":"run","Value":"def calcu_ma(df):\n df['ma'] = df['close'].rolling(365).mean()\n return df\n\n# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端\ndef bigquant_run(input_1, input_2, input_3):\n # 示例代码如下。在这里编写您的代码\n ins = input_1.read_pickle()['instruments']\n start_date = input_1.read_pickle()['start_date']\n end_date = input_1.read_pickle()['end_date']\n \n a_year_ago_dt = datetime.datetime.strptime(start_date,'%Y-%m-%d') - datetime.timedelta(252)\n start_date = datetime.datetime.strftime(a_year_ago_dt,'%Y-%m-%d')\n \n df = D.history_data(instruments=ins,start_date=start_date,end_date=end_date,fields=['close'])\n data = df.groupby('instrument').apply(calcu_ma)\n # long_pattern_list = data[data['close']>data['ma']].groupby('date').apply(lambda x:list(x.instrument))\n ds = DataSource.write_df(data)\n return Outputs(data_1=ds, data_2=None, data_3=None)\n","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_1","NodeId":"-110"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_2","NodeId":"-110"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_3","NodeId":"-110"}],"OutputPortsInternal":[{"Name":"data_1","NodeId":"-110","OutputType":null},{"Name":"data_2","NodeId":"-110","OutputType":null},{"Name":"data_3","NodeId":"-110","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":15,"Comment":"找出测试集上在年线以上的股票","CommentCollapsed":false},{"Id":"-123","ModuleId":"BigQuantSpace.join.join-v3","ModuleParameters":[{"Name":"on","Value":"date,instrument","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"how","Value":"inner","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"sort","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data1","NodeId":"-123"},{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"data2","NodeId":"-123"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-123","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":17,"Comment":"","CommentCollapsed":true},{"Id":"-130","ModuleId":"BigQuantSpace.filter.filter-v3","ModuleParameters":[{"Name":"expr","Value":"close> ma","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"output_left_data","Value":"False","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[{"DataSourceId":null,"TrainedModelId":null,"TransformModuleId":null,"Name":"input_data","NodeId":"-130"}],"OutputPortsInternal":[{"Name":"data","NodeId":"-130","OutputType":null},{"Name":"left_data","NodeId":"-130","OutputType":null}],"UsePreviousResults":true,"moduleIdForCode":18,"Comment":"过滤掉年线以下的股票","CommentCollapsed":false}],"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-8' Position='211,64,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-15' Position='70,183,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-24' Position='765,21,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-29' Position='381,188,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-35' Position='385,280,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-43' Position='539.640380859375,555.8771362304688,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-53' Position='249,375,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-60' Position='906,647,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-62' Position='1074,127,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-70' Position='1075.9508056640625,229.8525390625,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-76' Position='1082.024658203125,309.5821533203125,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-81' Position='1032,752,200,200'/><NodePosition Node='287d2cb0-f53c-4101-bdf8-104b137c8601-84' Position='376,467,200,200'/><NodePosition Node='-86' Position='1081.07373046875,377.0168151855469,200,200'/><NodePosition Node='-110' Position='773.7562255859375,255.39068603515625,200,200'/><NodePosition Node='-123' Position='1057.04150390625,448.1552429199219,200,200'/><NodePosition Node='-130' Position='1056.5402221679688,543.2975463867188,200,200'/></NodePositions><NodeGroups /></DataV1>"},"IsDraft":true,"ParentExperimentId":null,"WebService":{"IsWebServiceExperiment":false,"Inputs":[],"Outputs":[],"Parameters":[{"Name":"交易日期","Value":"","ParameterDefinition":{"Name":"交易日期","FriendlyName":"交易日期","DefaultValue":"","ParameterType":"String","HasDefaultValue":true,"IsOptional":true,"ParameterRules":[],"HasRules":false,"MarkupType":0,"CredentialDescriptor":null}}],"WebServiceGroupId":null,"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions></NodePositions><NodeGroups /></DataV1>"},"DisableNodesUpdate":false,"Category":"user","Tags":[],"IsPartialRun":true}
      In [53]:
      # 本代码由可视化策略环境自动生成 2018年5月14日 20:20
      # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
      
      
      m1 = M.instruments.v2(
          start_date='2010-01-01',
          end_date='2015-01-01',
          market='CN_STOCK_A',
          instrument_list='',
          max_count=0
      )
      
      m2 = M.advanced_auto_labeler.v2(
          instruments=m1.data,
          label_expr="""# #号开始的表示注释
      # 0. 每行一个,顺序执行,从第二个开始,可以使用label字段
      # 1. 可用数据字段见 https://bigquant.com/docs/data_history_data.html
      #   添加benchmark_前缀,可使用对应的benchmark数据
      # 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/big_expr.html>`_
      
      # 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
      shift(close, -5) / shift(open, -1)
      
      # 极值处理:用1%和99%分位的值做clip
      clip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))
      
      # 将分数映射到分类,这里使用20个分类
      all_wbins(label, 20)
      
      # 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
      where(shift(high, -1) == shift(low, -1), NaN, label)
      """,
          start_date='',
          end_date='',
          benchmark='000300.SHA',
          drop_na_label=True,
          cast_label_int=True
      )
      
      m3 = M.input_features.v1(
          features="""# #号开始的表示注释
      # 多个特征,每行一个,可以包含基础特征和衍生特征
      return_5
      return_10
      return_20
      avg_amount_0/avg_amount_5
      avg_amount_5/avg_amount_20
      rank_avg_amount_0/rank_avg_amount_5
      rank_avg_amount_5/rank_avg_amount_10
      rank_return_0
      rank_return_5
      rank_return_10
      rank_return_0/rank_return_5
      rank_return_5/rank_return_10
      pe_ttm_0
      """
      )
      
      m4 = M.general_feature_extractor.v6(
          instruments=m1.data,
          features=m3.data,
          start_date='',
          end_date='',
          before_start_days=0
      )
      
      m5 = M.derived_feature_extractor.v2(
          input_data=m4.data,
          features=m3.data,
          date_col='date',
          instrument_col='instrument'
      )
      
      m7 = M.join.v3(
          data1=m2.data,
          data2=m5.data,
          on='date,instrument',
          how='inner',
          sort=False
      )
      
      m13 = M.dropnan.v1(
          input_data=m7.data
      )
      
      m6 = M.stock_ranker_train.v5(
          training_ds=m13.data,
          features=m3.data,
          learning_algorithm='排序',
          number_of_leaves=30,
          minimum_docs_per_leaf=1000,
          number_of_trees=20,
          learning_rate=0.1,
          max_bins=1023,
          feature_fraction=1,
          m_lazy_run=False
      )
      
      m9 = M.instruments.v2(
          start_date=T.live_run_param('trading_date', '2015-01-01'),
          end_date=T.live_run_param('trading_date', '2017-01-01'),
          market='CN_STOCK_A',
          instrument_list='',
          max_count=0
      )
      
      m10 = M.general_feature_extractor.v6(
          instruments=m9.data,
          features=m3.data,
          start_date='',
          end_date='',
          before_start_days=0
      )
      
      m11 = M.derived_feature_extractor.v2(
          input_data=m10.data,
          features=m3.data,
          date_col='date',
          instrument_col='instrument'
      )
      
      m14 = M.dropnan.v1(
          input_data=m11.data
      )
      
      def calcu_ma(df):
          df['ma'] = df['close'].rolling(365).mean()
          return df
      
      # Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
      def m15_run_bigquant_run(input_1, input_2, input_3):
          # 示例代码如下。在这里编写您的代码
          ins = input_1.read_pickle()['instruments']
          start_date = input_1.read_pickle()['start_date']
          end_date = input_1.read_pickle()['end_date']
          
          a_year_ago_dt = datetime.datetime.strptime(start_date,'%Y-%m-%d') - datetime.timedelta(252)
          start_date = datetime.datetime.strftime(a_year_ago_dt,'%Y-%m-%d')
          
          df = D.history_data(instruments=ins,start_date=start_date,end_date=end_date,fields=['close'])
          data = df.groupby('instrument').apply(calcu_ma)
          # long_pattern_list = data[data['close']>data['ma']].groupby('date').apply(lambda x:list(x.instrument))
          ds = DataSource.write_df(data)
          return Outputs(data_1=ds, data_2=None, data_3=None)
      
      m15 = M.cached.v3(
          input_1=m9.data,
          run=m15_run_bigquant_run
      )
      
      m17 = M.join.v3(
          data1=m15.data_1,
          data2=m14.data,
          on='date,instrument',
          how='inner',
          sort=False
      )
      
      m18 = M.filter.v3(
          input_data=m17.data,
          expr='close> ma',
          output_left_data=False
      )
      
      m8 = M.stock_ranker_predict.v5(
          model=m6.model,
          data=m18.data,
          m_lazy_run=False
      )
      
      # 回测引擎:每日数据处理函数,每天执行一次
      def m12_handle_data_bigquant_run(context, data):
          
          date = data.current_dt.strftime('%Y-%m-%d')
          #------------------------------------------止损模块START--------------------------------------------
          positions = {e.symbol: p.cost_basis  for e, p in context.portfolio.positions.items()}
          # 新建当日止损股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
          current_stoploss_stock = []  # 将当天止损的股票整理到一个集合
          if len(positions) > 0:
              for i in positions.keys():
                  stock_cost = positions[i] 
                  stock_market_price = data.current(context.symbol(i), 'price') 
                  # 亏5%就止损
                  if (stock_market_price - stock_cost) / stock_cost <= -0.05:   
                      context.order_target_percent(context.symbol(i),0)     
                      current_stoploss_stock.append(i)
                  #    print('日期:',date,'股票:',i,'出现止损状况')
          #-------------------------------------------止损模块END---------------------------------------------
          
          #------------------------------------------止赢模块START--------------------------------------------
          # 新建当日止赢股票列表是为了handle_data 策略逻辑部分不再对该股票进行判断
          current_stopwin_stock = []  # 将当天止盈的股票整理到一个集合
          if len(positions) > 0:
              for i in positions.keys():
                  stock_cost = positions[i] 
                  stock_market_price = data.current(context.symbol(i), 'price') 
                  # 赚10%就止赢
                  if (stock_market_price - stock_cost ) / stock_cost>= 0.1:   
                      context.order_target_percent(context.symbol(i),0)     
                      current_stopwin_stock.append(i)
                  #    print('日期:',date,'股票:',i,'出现止盈状况')
          #-------------------------------------------止赢模块END---------------------------------------------
          
          
          
          # 按日期过滤得到今日的预测数据
          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.portfolio.positions.items()}
      
          # 2. 生成卖出订单:hold_days天之后才开始卖出;对持仓的股票,按机器学习算法预测的排序末位淘汰
          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:
                  if (instrument not in current_stopwin_stock) and (instrument not in current_stoploss_stock):
                      context.order_target(context.symbol(instrument), 0)
                      cash_for_sell -= positions[instrument]
                      if cash_for_sell <= 0:
                          break
      
          # 3. 生成买入订单:按机器学习算法预测的排序,买入前面的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 and (instrument not in current_stopwin_stock) and (instrument not in current_stoploss_stock):
                  context.order_value(context.symbol(instrument), cash)
      
      # 回测引擎:准备数据,只执行一次
      def m12_prepare_bigquant_run(context):
          pass
      
      # 回测引擎:初始化函数,只执行一次
      def m12_initialize_bigquant_run(context):
          # 加载预测数据
          context.ranker_prediction = context.options['data'].read_df()
      
          # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
          context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
          # 预测数据,通过options传入进来,使用 read_df 函数,加载到内存 (DataFrame)
          # 设置买入的股票数量,这里买入预测股票列表排名靠前的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
          context.options['hold_days'] = 5
      
      m12 = M.trade.v3(
          instruments=m9.data,
          options_data=m8.predictions,
          start_date='',
          end_date='',
          handle_data=m12_handle_data_bigquant_run,
          prepare=m12_prepare_bigquant_run,
          initialize=m12_initialize_bigquant_run,
          volume_limit=0,
          order_price_field_buy='open',
          order_price_field_sell='close',
          capital_base=1000000,
          benchmark='000300.SHA',
          auto_cancel_non_tradable_orders=True,
          data_frequency='daily',
          price_type='后复权',
          plot_charts=True,
          backtest_only=False,
          amount_integer=False
      )
      
      [2018-05-14 20:18:00.899762] INFO: bigquant: instruments.v2 开始运行..
      [2018-05-14 20:18:00.975890] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:00.977897] INFO: bigquant: instruments.v2 运行完成[0.078161s].
      [2018-05-14 20:18:01.009427] INFO: bigquant: advanced_auto_labeler.v2 开始运行..
      [2018-05-14 20:18:01.082476] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.085797] INFO: bigquant: advanced_auto_labeler.v2 运行完成[0.076403s].
      [2018-05-14 20:18:01.094296] INFO: bigquant: input_features.v1 开始运行..
      [2018-05-14 20:18:01.218357] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.219812] INFO: bigquant: input_features.v1 运行完成[0.125553s].
      [2018-05-14 20:18:01.390981] INFO: bigquant: general_feature_extractor.v6 开始运行..
      [2018-05-14 20:18:01.419558] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.421129] INFO: bigquant: general_feature_extractor.v6 运行完成[0.030176s].
      [2018-05-14 20:18:01.431791] INFO: bigquant: derived_feature_extractor.v2 开始运行..
      [2018-05-14 20:18:01.461124] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.463402] INFO: bigquant: derived_feature_extractor.v2 运行完成[0.031624s].
      [2018-05-14 20:18:01.475342] INFO: bigquant: join.v3 开始运行..
      [2018-05-14 20:18:01.507996] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.509417] INFO: bigquant: join.v3 运行完成[0.034002s].
      [2018-05-14 20:18:01.519012] INFO: bigquant: dropnan.v1 开始运行..
      [2018-05-14 20:18:01.550755] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.552294] INFO: bigquant: dropnan.v1 运行完成[0.033335s].
      [2018-05-14 20:18:01.581528] INFO: bigquant: stock_ranker_train.v5 开始运行..
      [2018-05-14 20:18:01.641098] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.642729] INFO: bigquant: stock_ranker_train.v5 运行完成[0.06124s].
      [2018-05-14 20:18:01.654011] INFO: bigquant: instruments.v2 开始运行..
      [2018-05-14 20:18:01.662557] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.664885] INFO: bigquant: instruments.v2 运行完成[0.010899s].
      [2018-05-14 20:18:01.814918] INFO: bigquant: general_feature_extractor.v6 开始运行..
      [2018-05-14 20:18:01.824717] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.826124] INFO: bigquant: general_feature_extractor.v6 运行完成[0.011222s].
      [2018-05-14 20:18:01.838588] INFO: bigquant: derived_feature_extractor.v2 开始运行..
      [2018-05-14 20:18:01.845413] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.846922] INFO: bigquant: derived_feature_extractor.v2 运行完成[0.008364s].
      [2018-05-14 20:18:01.859678] INFO: bigquant: dropnan.v1 开始运行..
      [2018-05-14 20:18:01.866856] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.868643] INFO: bigquant: dropnan.v1 运行完成[0.008996s].
      [2018-05-14 20:18:01.884766] INFO: bigquant: cached.v3 开始运行..
      [2018-05-14 20:18:01.889239] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.891102] INFO: bigquant: cached.v3 运行完成[0.006477s].
      [2018-05-14 20:18:01.907978] INFO: bigquant: join.v3 开始运行..
      [2018-05-14 20:18:01.912027] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.913770] INFO: bigquant: join.v3 运行完成[0.005815s].
      [2018-05-14 20:18:01.924508] INFO: bigquant: filter.v3 开始运行..
      [2018-05-14 20:18:01.931458] INFO: bigquant: 命中缓存
      [2018-05-14 20:18:01.933357] INFO: bigquant: filter.v3 运行完成[0.008854s].
      [2018-05-14 20:18:01.959727] INFO: bigquant: stock_ranker_predict.v5 开始运行..
      [2018-05-14 20:18:02.582027] INFO: df2bin: prepare data: prediction ..
      
      /var/app/enabled/bigranker/bigrankerservicev2/pybin.py:148: SettingWithCopyWarning: 
      A value is trying to be set on a copy of a slice from a DataFrame.
      Try using .loc[row_indexer,col_indexer] = value instead
      
      See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
      /var/app/enabled/bigranker/bigrankerservicev2/pybin.py:151: SettingWithCopyWarning: 
      A value is trying to be set on a copy of a slice from a DataFrame.
      Try using .loc[row_indexer,col_indexer] = value instead
      
      See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
      
      [2018-05-14 20:18:08.758997] INFO: stock_ranker_predict: 准备预测: 319197 行
      [2018-05-14 20:18:12.861782] INFO: bigquant: stock_ranker_predict.v5 运行完成[10.902036s].
      [2018-05-14 20:18:13.015760] INFO: bigquant: backtest.v7 开始运行..
      [2018-05-14 20:18:13.224298] INFO: algo: set price type:backward_adjusted
      
      /var/app/enabled/empyrical/stats.py:534: RuntimeWarning: invalid value encountered in double_scalars
        sortino = mu / dsr
      /var/app/enabled/empyrical/stats.py:534: RuntimeWarning: divide by zero encountered in double_scalars
        sortino = mu / dsr
      
      [2018-05-14 20:19:00.157518] INFO: Performance: Simulated 488 trading days out of 488.
      [2018-05-14 20:19:00.159147] INFO: Performance: first open: 2015-01-05 01:30:00+00:00
      [2018-05-14 20:19:00.161921] INFO: Performance: last close: 2016-12-30 07:00:00+00:00
      [注意] 有 142 笔卖出是在多天内完成的。当日卖出股票超过了当日股票交易的0%会出现这种情况。
      
      /var/app/enabled/pandas/core/generic.py:1138: PerformanceWarning: 
      your performance may suffer as PyTables will pickle object types that it cannot
      map directly to c-types [inferred_type->mixed,key->block4_values] [items->['LOG', 'POS_FAC', 'TRA_FAC', 'orders', 'period_label', 'positions', 'transactions']]
      
        return pytables.to_hdf(path_or_buf, key, self, **kwargs)
      /var/app/enabled/pandas/core/indexing.py:141: SettingWithCopyWarning: 
      A value is trying to be set on a copy of a slice from a DataFrame
      
      See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
        self._setitem_with_indexer(indexer, value)
      
      • 收益率64.09%
      • 年化收益率29.14%
      • 基准收益率-6.33%
      • 阿尔法0.28
      • 贝塔0.33
      • 夏普比率0.99
      • 胜率0.571
      • 盈亏比1.123
      • 收益波动率25.94%
      • 信息比率1.02
      • 最大回撤26.0%
      [2018-05-14 20:19:04.138727] INFO: bigquant: backtest.v7 运行完成[51.122952s].
      

      (skura69) #10

      hi,最后这个年线以上买入的策略,前面会有很长的一段空白是选不出票的,看收益率前面那段直线,以此为模板修改的策略也存在这个问题,开始交易后没有股票推荐,这个问题该怎么解决呢?


      (eqsxin) #11

      @skura69 其实很简单啊 ,取数据的时候,多往前面取一段时间的数据。

      比如将252修改为500,这样模拟交易,第二天应该能出信号。