AI量化知识树

开发传统趋势策略

由iquant创建,最终由iquant 被浏览 117 用户

导语

本文以双均线策略为例,如何开发一个传统的趋势跟踪策略。

在BigQuant策略平台上,除了开发AI策略,还可以开发传统策略,比如趋势跟踪、套利、事件驱动策略、多因子选股策略。本文以双均线策略为例,帮助大家更好地理解BigQuant回测机制

双均线策略的策略思想是:当短期均线上穿长期均线时,形成金叉,此时买入股票。当短期均线下穿长期均线时,形成死叉,此时卖出股票。研究表明,双均线系统虽然简单,但只要严格执行,也能长期盈利。

交易逻辑为:

  • 当收盘价5日均线大于10日均线时,以第二日开盘价买入;
  • 买入后,当收盘价的5日均线小于10日均线时,以第二日开盘价卖出;

构建策略流程

我们可以在AIStudio3.0环境下构建如下流程:

第一步,提取数据,设置回测起止日期。

第二步,通过sql语句定义买入和卖出信号,并提取数据:

  • 定义5日均线大于50日均线作为买入条件信号buy_condition,
  • 定义5日均线小于50日均线作为卖出条件信号sell_condition。
sql = f"""
SELECT
    date,
    instrument,
    IF(m_avg(close,5) > m_avg(close,10), 1, 0) AS buy_signal,
    IF(m_avg(close,5) < m_avg(close,10), 1, 0) AS sell_signal
FROM cn_stock_factors
QUALIFY COLUMNS(*) IS NOT NULL
AND date BETWEEN DATE '{sd}' - INTERVAL 0 DAY AND '{ed}'
ORDER BY date,instrument
"""
data = dai.query(sql,full_db_scan=True).df()

第三步,根据策略修改交易引擎的初始化函数:

 # 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
    context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
 # 设置持仓天数为3,持股票数为5,等权持有
    context.holding_days = 3
    context.target_hold_count = 5
    context.target_percent_per_instrument = 1.0 / context.target_hold_count

本例中,我们设置股票的买入手续费按照成交额的0.0003收取,卖出手续费按成交额的0.0013收取,不足5元按照5元收取。

第四步,修改K线处理函数:

def m_handle_data_bigquant_run(context, data):
    
    # 每5个交易日调仓一次
    if context.trading_day_index % context.holding_days != 0:
        return

    # 获取当前日期
    current_date = data.current_dt.strftime("%Y-%m-%d")
    # 获取当日数据
    current_day_data = context.data[context.data["date"] == current_date]
    
    # 获取当日符合买入/卖出条件的股票列表
    try:
        buy_stock = set(current_day_data[current_day_data['buy_signal'] == 1].iloc[:context.target_hold_count]['instrument']) # 当日符合买入条件的股票(10只)
    except:
        buy_stock=[]
    try:
        sell_stock = set(current_day_data[current_day_data['sell_signal']==1]['instrument'])# 当日符合卖出条件的股票
    except:
        sell_stock = []
    
    # 获取当前已持有股票
    current_hold_instruments = set(context.get_account_positions().keys())
    hold_num=len(current_hold_instruments)

    # 需要卖出的股票:已有持仓中符合卖出条件的股票
    sell_set = [i for i in current_hold_instruments if i in sell_stock]
    # 需要买入的股票:没有持仓且符合买入条件的股票
    buy_set = [i for i in buy_stock if i not in current_hold_instruments]

    # 卖出不在目标持有列表中的股票
    for instrument in sell_set:
        context.order_target_percent(instrument, 0)
        hold_num-=1

    # 当日还允许买入建仓的股票数目
    stock_can_buy_num = context.target_hold_count - hold_num
    stock_to_buy_num = min(stock_can_buy_num,len(buy_set))
    
    # 如果当天没有买入的股票,就返回
    if stock_to_buy_num == 0:
        return
    # 记录已经买入的股票数量
    buy_num = 0

    # 买入目标持有列表中的股票
    for instrument in buy_set:
        if buy_num < stock_to_buy_num:
            context.order_target_percent(instrument, context.target_percent_per_instrument)
            buy_num += 1

策略案例

https://bigquant.com/codesharev2/51f69b7a-caba-4893-a12d-a432c44036c5

\

{link}