Xgboost在AIstudio运行和回测正常,但是运行模拟交易失败
由bqvpogtl创建,最终由xiaoshao 被浏览 5 用户
from bigmodule import M
# <aistudiograph>
# @param(id="m7", name="initialize")
# 交易引擎:初始化函数, 只执行一次
def m7_initialize_bigquant_run(context):
import math
import numpy as np
from bigtrader.finance.commission import PerOrder
# 系统已经设置了默认的交易手续费和滑点, 要修改手续费可使用如下函数
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 = np.array(
[1 / math.log(i + 2) for i in range(0, stock_count)]
)
context.stock_weights = context.stock_weights / context.stock_weights.sum()
# 设置每只股票占用的最大资金比例
context.max_cash_per_instrument = 0.2
context.options["hold_days"] = 5
# @param(id="m7", name="before_trading_start")
# 交易引擎:每个单位时间开盘前调用一次。
def m7_before_trading_start_bigquant_run(context, data):
# 盘前处理,订阅行情等
pass
# @param(id="m7", name="handle_tick")
# 交易引擎:tick数据处理函数,每个tick执行一次
def m7_handle_tick_bigquant_run(context, tick):
pass
# @param(id="m7", name="handle_data")
# 回测引擎:每日数据处理函数, 每天执行一次
def m7_handle_data_bigquant_run(context, data):
# 按日期过滤得到今日的预测数据
ranker_prediction = context.data[
context.data.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: 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: e for e, p in context.portfolio.positions.items()}
instruments = list(
reversed(
list(
ranker_prediction.instrument[
ranker_prediction.instrument.apply(lambda x: x in equities)
]
)
)
)
for instrument in instruments:
context.order_target(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(instrument, cash)
# @param(id="m7", name="handle_trade")
# 交易引擎:成交回报处理函数,每个成交发生时执行一次
def m7_handle_trade_bigquant_run(context, trade):
pass
# @param(id="m7", name="handle_order")
# 交易引擎:委托回报处理函数,每个委托变化时执行一次
def m7_handle_order_bigquant_run(context, order):
pass
# @param(id="m7", name="after_trading")
# 交易引擎:盘后处理函数,每日盘后执行一次
def m7_after_trading_bigquant_run(context, data):
pass
# @module(position="-410,-958", comment="""因子特征,用表达式构建因子""")
m1 = M.input_features_dai.v30(
mode="""表达式""",
expr="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home / cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
-- 数据使用: 表名.字段名, 对于没有指定表名的列,会从 expr_tables 推断
close / m_lag(close,6) AS return_5
close / m_lag(close,11) AS return_10
close / m_lag(close,21) AS return_20
amount / m_avg(amount,6)
m_avg(amount,6) / m_avg(amount,11)
c_pct_rank(amount) / c_pct_rank(m_avg(amount,6))
c_pct_rank(m_avg(amount,6)) / c_pct_rank(m_avg(amount,11))
close / m_lag(close,1) AS _return_0
c_pct_rank(_return_0) AS rank_return_0
close / m_lag(close,6) AS _return_5
c_pct_rank(_return_5) AS rank_return_5
close / m_lag(close,11) AS _return_10
c_pct_rank(_return_10) AS rank_return_10
rank_return_0 / rank_return_5
rank_return_5 / rank_return_10
""",
expr_filters="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
-- c_pct_rank(short_return) BETWEEN 0.4 AND 0.6
-- rank_returns <= 10
list_days > 260
st_status = 0
close >= 50""",
expr_tables="""cn_stock_prefactors""",
extra_fields="""date, instrument""",
order_by="""date, instrument""",
expr_drop_na=True,
sql="""-- 使用DAI SQL获取数据,构建因子等,如下是一个例子作为参考
-- DAI SQL 语法: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-sql%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B
SELECT
-- 在这里输入因子表达式
-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
close / m_lag(close,6) AS return_5
close / m_lag(close,11) AS return_10
close / m_lag(close,21) AS return_20
amount / m_avg(amount,6)
m_avg(amount,6) / m_avg(amount,11)
c_pct_rank(amount) / c_pct_rank(m_avg(amount,6))
c_pct_rank(m_avg(amount,6)) / c_pct_rank(m_avg(amount,11))
close / m_lag(close,1) AS _return_0
c_pct_rank(_return_0) AS rank_return_0
close / m_lag(close,6) AS _return_5
c_pct_rank(_return_5) AS rank_return_5
close / m_lag(close,11) AS _return_10
c_pct_rank(_return_10) AS rank_return_10
rank_return_0 / rank_return_5
rank_return_5 / rank_return_10
pe_ttm
-- 日期和股票代码
date, instrument
FROM
-- 预计算因子 cn_stock_factors https://bigquant.com/data/datasources/cn_stock_factors
cn_stock_prefactors
WHERE
-- WHERE 过滤,在窗口等计算算子之前执行
-- 剔除ST股票
st_status = 0
QUALIFY
-- QUALIFY 过滤,在窗口等计算算子之后执行,比如 m_lag(close, 3) AS close_3,对于 close_3 的过滤需要放到这里
-- 去掉有空值的行
COLUMNS(*) IS NOT NULL
-- 按日期和股票代码排序,从小到大
ORDER BY date, instrument
""",
extract_data=False,
m_name="""m1"""
)
# @module(position="-594,-803", comment="""+ 数据标注""", comment_collapsed=True)
m2 = M.input_features_dai.v30(
input_1=m1.data,
mode="""表达式""",
expr="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home / cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
-- 数据使用: 表名.字段名, 对于没有指定表名的列,会从 expr_tables 推断
input_1.* EXCLUDE(date, instrument)
m_lead(close, 5) / m_lead(open, 1) AS _future_return
c_quantile_cont(_future_return, 0.01) AS _future_return_1pct
c_quantile_cont(_future_return, 0.99) AS _future_return_99pct
clip(_future_return, _future_return_1pct, _future_return_99pct) AS _clipped_return
c_cbins(_clipped_return, 20) AS label
""",
expr_filters="""-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
-- st_status = 0
-- 从训练数据中移除第二天涨停和跌停数据
m_lead(high, 1) != m_lead(low, 1)""",
expr_tables="""cn_stock_bar1d""",
extra_fields="""date, instrument""",
order_by="""date, instrument""",
expr_drop_na=True,
sql="""-- 使用DAI SQL获取数据,构建因子等,如下是一个例子作为参考
-- DAI SQL 语法: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-sql%E5%85%A5%E9%97%A8%E6%95%99%E7%A8%8B
SELECT
-- 在这里输入因子表达式
-- DAI SQL 算子/函数: https://bigquant.com/wiki/doc/dai-PLSbc1SbZX#h-%E5%87%BD%E6%95%B0
-- 数据&字段: 数据文档 https://bigquant.com/data/home
c_rank(volume) AS rank_volume,
close / m_lag(close, 1) as return_0,
-- 日期和股票代码
date, instrument
FROM
-- 预计算因子 cn_stock_prefactors https://bigquant.com/data/datasources/cn_stock_prefactors
cn_stock_prefactors
-- 如果要使用输入数据源,需要在这里join进来
-- JOIN input_1 USING(date, instrument)
WHERE
-- WHERE 过滤,在窗口等计算算子之前执行
-- 剔除ST股票
st_status = 0
QUALIFY
-- QUALIFY 过滤,在窗口等计算算子之后执行,比如 m_lag(close, 3) AS close_3,对于 close_3 的过滤需要放到这里
-- 去掉有空值的行
COLUMNS(*) IS NOT NULL
-- 按日期和股票代码排序,从小到大
ORDER BY date, instrument
""",
extract_data=False,
m_name="""m2"""
)
# @module(position="-592,-713", comment="""抽取训练数据""", comment_collapsed=True)
m3 = M.extract_data_dai.v19(
sql=m2.data,
start_date="""2020-01-01""",
start_date_bound_to_trading_date=False,
end_date="""2022-12-31""",
end_date_bound_to_trading_date=True,
before_start_days=90,
keep_before=False,
debug=False,
m_name="""m3"""
)
# @module(position="-190,-778", comment="""抽取预测数据""", comment_collapsed=True)
m4 = M.extract_data_dai.v19(
sql=m1.data,
start_date="""2023-01-01""",
start_date_bound_to_trading_date=False,
end_date="""2024-05-26""",
end_date_bound_to_trading_date=True,
before_start_days=90,
keep_before=False,
debug=False,
m_cached=False,
m_name="""m4"""
)
# @module(position="-404,-613", comment="""""", comment_collapsed=True)
m5 = M.xgboost.v6(
train_ds=m3.data,
test_ds=m4.data,
objective="""排序学习-ranknet""",
number_of_leaves=30,
min_docs_per_leaf=1,
number_of_trees=6,
number_of_depth=5,
learning_rate=0.1,
max_bins=1023,
feature_fraction=1,
data_row_fraction=1,
params="""# 训练参数
# https://xgboost.readthedocs.io/en/stable/parameter.html
{
# 以 [参数名: 参数值,] 的方式进行设置
# 以 [#] 开头的设置或文本将被忽略
# 例如:使用排序任务的目标函数
# "objective": "rank:pairwise",
}
""",
log_level="""信息""",
plot_charts=True,
use_gpu=False,
m_name="""m5"""
)
# @module(position="-434,-510", comment="""""", comment_collapsed=True)
m7 = M.bigtrader.v39(
data=m5.predictions,
start_date="""""",
end_date="""""",
initialize=m7_initialize_bigquant_run,
before_trading_start=m7_before_trading_start_bigquant_run,
handle_tick=m7_handle_tick_bigquant_run,
handle_data=m7_handle_data_bigquant_run,
handle_trade=m7_handle_trade_bigquant_run,
handle_order=m7_handle_order_bigquant_run,
after_trading=m7_after_trading_bigquant_run,
capital_base=1000000,
frequency="""daily""",
product_type="""股票""",
rebalance_period_type="""交易日""",
rebalance_period_days="""5""",
rebalance_period_roll_forward=True,
backtest_engine_mode="""标准模式""",
before_start_days=0,
volume_limit=1,
order_price_field_buy="""open""",
order_price_field_sell="""open""",
benchmark="""沪深300指数""",
plot_charts=True,
debug=False,
backtest_only=False,
m_name="""m7"""
)
# </aistudiograph>
TypeError: not all arguments converted during string formatting