复制链接
克隆策略

日内均线金叉开仓策略-分钟

版本 v1.0

目录

交易规则

策略构建步骤

策略的实现

正文

一、交易规则

  • 1分钟频率回测,如果分钟K线的短期均线上穿长期均线平空开多,短期均线下穿长期均线平多。

每个交易日尾盘需要清仓。

二、策略构建步骤

1、确定股票池和回测时间

  • 通过证券代码列表输入回测的起止日期

2、确定买卖条件信号

  • 计算短期短期均线与长期均线,短期均线上穿长期均线平空开多,短期均线下穿长期均线平多。

4、回测

  • 通过 trade 模块中的初始化函数定义交易手续费和滑点;
  • 通过 trade 模块中的主函数(handle函数)查看每日的买卖交易信号,按照买卖原则执行相应的买入/卖出/调仓操作。

三、策略的实现

可视化策略实现如下:

    {"description":"实验创建于2021/11/30","graph":{"edges":[{"to_node_id":"-113:instruments","from_node_id":"-551:data"}],"nodes":[{"node_id":"-551","module_id":"BigQuantSpace.instruments.instruments-v2","parameters":[{"name":"start_date","value":"2021-11-11","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"2021-11-23","type":"Literal","bound_global_parameter":null},{"name":"market","value":"CN_STOCK_A","type":"Literal","bound_global_parameter":null},{"name":"instrument_list","value":"000333.SZA","type":"Literal","bound_global_parameter":null},{"name":"max_count","value":0,"type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"rolling_conf","node_id":"-551"}],"output_ports":[{"name":"data","node_id":"-551"}],"cacheable":true,"seq_num":2,"comment":"","comment_collapsed":true},{"node_id":"-113","module_id":"BigQuantSpace.hftrade.hftrade-v2","parameters":[{"name":"start_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"end_date","value":"","type":"Literal","bound_global_parameter":null},{"name":"initialize","value":"# 交易引擎:初始化函数,只执行一次\ndef bigquant_run(context):\n #输出关键日志\n msg = \"initialize:\" \n context.write_log(msg, stdout=1)\n \n context.ins = context.instruments[0] #从传入参数中获取需要交易的合约\n \n \n context.short_ma = 5 #均线短周期参数\n context.long_ma = 20 #均线长周期参数\n context.order_pct =0.1 #每只股票占用总资金的百分比\n context.closetime = \"14:56\"\n context.set_slippage_value(volume_limit=1)\n context.set_stock_t1(0) #0表示回测支持当天买和卖。1表示不支持t0\n","type":"Literal","bound_global_parameter":null},{"name":"before_trading_start","value":"# 交易引擎:每个单位时间开盘前调用一次。\ndef bigquant_run(context, data):\n \"\"\"盘前处理,策略盘前交易函数,每日盘前触发一次。可以在该函数中一些启动前的准备,如订阅行情等\"\"\"\n \n # 输出关键日志\n msg = \"before_trading\"\n context.write_log(msg, stdout=1)\n # 订阅要交易的合约的行情\n context.subscribe(context.ins)\n","type":"Literal","bound_global_parameter":null},{"name":"handle_tick","value":"# 交易引擎:tick数据处理函数,每个tick执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_data","value":"# 交易引擎:bar数据处理函数,每个时间单位执行一次\ndef bigquant_run(context, data):\n \"\"\"行情通知函数\"\"\"\n #获取当前时间\n cur_date = data.current_dt\n cur_hm = cur_date.strftime('%H:%M')\n \n # 获取账户资金\n trading_account = context.get_trading_account()\n total_portfolio = trading_account.portfolio_value\n \n for instr in context.instruments:\n #获取持仓情况\n position = context.get_position(instr)\n\n #最新价格\n price = data.current(instr, \"close\")\n \n \n #尾盘平仓\n if(cur_hm>=context.closetime and cur_hm<=\"15:00\" and position.current_qty>0):\n #有持仓则卖出 \n if (position.avail_qty != 0):\n rv = context.order(instr, -position.avail_qty, price, order_type=OrderType.MARKET)\n msg = \"{} 尾盘卖出{} 最新价={:.2f} 下单函数返回={}\".format(cur_date,context.ins,price,rv)\n context.write_log(msg, stdout=1) \n #尾盘不开新仓,直接返回\n continue\n \n #获取1m历史数据数据\n \n hist = context.history_data(instr, [\"open\",\"high\",\"low\",\"close\"], context.long_ma + 5, \"1m\")\n if hist.shape[0] < 2:\n continue\n\n #计算短周期和长周期均线\n hist['short_ma'] = hist['close'].rolling(context.short_ma).mean()\n hist['long_ma'] = hist['close'].rolling(context.long_ma).mean()\n \n #短周期均线上穿越长周期均线买入\n if(hist.iloc[-2]['short_ma']<=hist.iloc[-2]['long_ma'] and hist.iloc[-1]['short_ma']>hist.iloc[-1]['long_ma']):\n #当前没有持仓则市价买入\n if (position.current_qty == 0):\n #计算买入此股票的数量,不要超过总资金的某个比例\n order_num = int(total_portfolio*context.order_pct/price/100)*100\n rv = context.order(instr, order_num, price, order_type=OrderType.MARKET)\n msg = \"{} 买入{} 最新价={:.2f} 下单函数返回={}\".format(cur_date,context.ins,price,rv)\n context.write_log(msg, stdout=1) \n \n \n #短周期均线下穿越长周期均线卖出\n elif(hist.iloc[-2]['short_ma']>=hist.iloc[-2]['long_ma'] and hist.iloc[-1]['short_ma']<hist.iloc[-1]['long_ma']):\n #有持仓则卖出 \n if (position.current_qty != 0):\n rv = context.order(instr, -position.avail_qty, price, order_type=OrderType.MARKET)\n msg = \"{} 卖出{} 最新价={:.2f} 下单函数返回={}\".format(cur_date,context.ins,price,rv)\n context.write_log(msg, stdout=1) \n \n","type":"Literal","bound_global_parameter":null},{"name":"handle_trade","value":"# 交易引擎:成交回报处理函数,每个成交发生时执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"handle_order","value":"# 交易引擎:委托回报处理函数,每个委托变化时执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"after_trading","value":"# 交易引擎:盘后处理函数,每日盘后执行一次\ndef bigquant_run(context, data):\n pass\n","type":"Literal","bound_global_parameter":null},{"name":"capital_base","value":"100000","type":"Literal","bound_global_parameter":null},{"name":"frequency","value":"minute","type":"Literal","bound_global_parameter":null},{"name":"price_type","value":"真实价格","type":"Literal","bound_global_parameter":null},{"name":"product_type","value":"股票","type":"Literal","bound_global_parameter":null},{"name":"before_start_days","value":"0","type":"Literal","bound_global_parameter":null},{"name":"benchmark","value":"000300.HIX","type":"Literal","bound_global_parameter":null},{"name":"plot_charts","value":"True","type":"Literal","bound_global_parameter":null},{"name":"disable_cache","value":"False","type":"Literal","bound_global_parameter":null},{"name":"show_debug_info","value":"False","type":"Literal","bound_global_parameter":null},{"name":"backtest_only","value":"False","type":"Literal","bound_global_parameter":null}],"input_ports":[{"name":"instruments","node_id":"-113"},{"name":"options_data","node_id":"-113"},{"name":"history_ds","node_id":"-113"},{"name":"benchmark_ds","node_id":"-113"}],"output_ports":[{"name":"raw_perf","node_id":"-113"}],"cacheable":false,"seq_num":4,"comment":"","comment_collapsed":true}],"node_layout":"<node_postions><node_position Node='-551' Position='31,60,200,200'/><node_position Node='-113' Position='6,182,200,200'/></node_postions>"},"nodes_readonly":false,"studio_version":"v2"}
    In [2]:
    # 本代码由可视化策略环境自动生成 2021年12月10日 10:50
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    # 交易引擎:初始化函数,只执行一次
    def m4_initialize_bigquant_run(context):
        #输出关键日志
        msg = "initialize:" 
        context.write_log(msg, stdout=1)
        
        context.ins = context.instruments[0] #从传入参数中获取需要交易的合约
        
        
        context.short_ma = 5 #均线短周期参数
        context.long_ma = 20 #均线长周期参数
        context.order_pct =0.1 #每只股票占用总资金的百分比
        context.closetime = "14:56"
        context.set_slippage_value(volume_limit=1)
        context.set_stock_t1(0) #0表示回测支持当天买和卖。1表示不支持t0
    
    # 交易引擎:每个单位时间开盘前调用一次。
    def m4_before_trading_start_bigquant_run(context, data):
        """盘前处理,策略盘前交易函数,每日盘前触发一次。可以在该函数中一些启动前的准备,如订阅行情等"""
        
        # 输出关键日志
        msg = "before_trading"
        context.write_log(msg, stdout=1)
        # 订阅要交易的合约的行情
        context.subscribe(context.ins)
    
    # 交易引擎:tick数据处理函数,每个tick执行一次
    def m4_handle_tick_bigquant_run(context, data):
        pass
    
    # 交易引擎:bar数据处理函数,每个时间单位执行一次
    def m4_handle_data_bigquant_run(context, data):
        """行情通知函数"""
        #获取当前时间
        cur_date =  data.current_dt
        cur_hm = cur_date.strftime('%H:%M')
        
        # 获取账户资金
        trading_account = context.get_trading_account()
        total_portfolio = trading_account.portfolio_value
            
        for instr in context.instruments:
            #获取持仓情况
            position = context.get_position(instr)
    
            #最新价格
            price = data.current(instr, "close")
            
            
            #尾盘平仓
            if(cur_hm>=context.closetime and cur_hm<="15:00" and position.current_qty>0):
                #有持仓则卖出    
                if (position.avail_qty != 0):
                    rv = context.order(instr, -position.avail_qty, price, order_type=OrderType.MARKET)
                    msg = "{} 尾盘卖出{}  最新价={:.2f} 下单函数返回={}".format(cur_date,context.ins,price,rv)
                    context.write_log(msg, stdout=1)   
                #尾盘不开新仓,直接返回
                continue
                
            #获取1m历史数据数据
        
            hist = context.history_data(instr, ["open","high","low","close"], context.long_ma + 5, "1m")
            if hist.shape[0] < 2:
                continue
    
            #计算短周期和长周期均线
            hist['short_ma'] = hist['close'].rolling(context.short_ma).mean()
            hist['long_ma'] = hist['close'].rolling(context.long_ma).mean()
            
            #短周期均线上穿越长周期均线买入
            if(hist.iloc[-2]['short_ma']<=hist.iloc[-2]['long_ma'] and hist.iloc[-1]['short_ma']>hist.iloc[-1]['long_ma']):
                #当前没有持仓则市价买入
                if (position.current_qty == 0):
                    #计算买入此股票的数量,不要超过总资金的某个比例
                    order_num = int(total_portfolio*context.order_pct/price/100)*100
                    rv = context.order(instr, order_num, price, order_type=OrderType.MARKET)
                    msg = "{} 买入{}  最新价={:.2f} 下单函数返回={}".format(cur_date,context.ins,price,rv)
                    context.write_log(msg, stdout=1) 
                    
           
            #短周期均线下穿越长周期均线卖出
            elif(hist.iloc[-2]['short_ma']>=hist.iloc[-2]['long_ma'] and hist.iloc[-1]['short_ma']<hist.iloc[-1]['long_ma']):
                #有持仓则卖出    
                if (position.current_qty != 0):
                    rv = context.order(instr, -position.avail_qty, price, order_type=OrderType.MARKET)
                    msg = "{} 卖出{}  最新价={:.2f} 下单函数返回={}".format(cur_date,context.ins,price,rv)
                    context.write_log(msg, stdout=1)   
                    
    
    # 交易引擎:成交回报处理函数,每个成交发生时执行一次
    def m4_handle_trade_bigquant_run(context, data):
        pass
    
    # 交易引擎:委托回报处理函数,每个委托变化时执行一次
    def m4_handle_order_bigquant_run(context, data):
        pass
    
    # 交易引擎:盘后处理函数,每日盘后执行一次
    def m4_after_trading_bigquant_run(context, data):
        pass
    
    
    m2 = M.instruments.v2(
        start_date='2021-11-11',
        end_date='2021-11-23',
        market='CN_STOCK_A',
        instrument_list='000333.SZA',
        max_count=0
    )
    
    m4 = M.hftrade.v2(
        instruments=m2.data,
        start_date='',
        end_date='',
        initialize=m4_initialize_bigquant_run,
        before_trading_start=m4_before_trading_start_bigquant_run,
        handle_tick=m4_handle_tick_bigquant_run,
        handle_data=m4_handle_data_bigquant_run,
        handle_trade=m4_handle_trade_bigquant_run,
        handle_order=m4_handle_order_bigquant_run,
        after_trading=m4_after_trading_bigquant_run,
        capital_base=100000,
        frequency='minute',
        price_type='真实价格',
        product_type='股票',
        before_start_days='0',
        benchmark='000300.HIX',
        plot_charts=True,
        disable_cache=False,
        show_debug_info=False,
        backtest_only=False
    )
    
    • 收益率-0.73%
    • 年化收益率nan%
    • 基准收益率0.3%
    • 阿尔法-0.21
    • 贝塔-0.01
    • 夏普比率-31.29
    • 胜率0.19
    • 盈亏比0.43
    • 收益波动率0.75%
    • 信息比率-0.39
    • 最大回撤0.73%
    bigcharts-data-start/{"__type":"tabs","__id":"bigchart-601801425adc4b92a2f098b51582a886"}/bigcharts-data-end