Home >  > 极智量化520双均线

极智量化520双均线

一、螺纹钢回测效果:

可以显示均线:

代码:

备注:
如果回测结果只显示3年,那时因为 SetBarInterval这里的问题。

# 策略名称:双均线策略(5日上穿20日做多,下穿做空)+ 均线显示
# 适用周期:日线
# 策略逻辑:
#   金叉(5日均线上穿20日均线)→ 开多仓
#   死叉(5日均线下穿20日均线)→ 开空仓
#   同时在K线图上绘制5日和20日均线

import numpy as np
import talib

# -------------------- 初始化函数 --------------------
def initialize(context):
    # 获取当前基准合约,订阅日线数据
    contract = Symbol()
     #SetBarInterval(contract, 'D', 1, 500)  # 日线,500根K线
    SetBarInterval(contract, 'D', 1, 'A')  #使用所有可用历史数据
    
    # 设置初始资金
    SetInitCapital(1000000)
    
    # 发单方式:K线完成后发单
    SetOrderWay(2)
    
    # 交易方向:双向
    SetTradeDirection(0)
    
    # 设置滑点
    SetSlippage(1)
    
    # 设置日志级别
    SetLogLevel(2)
    
    # 定义均线周期参数
    context.fast_period = 5   # 快速均线周期
    context.slow_period = 20  # 慢速均线周期
    
    # 定义状态变量(用于记录上一次信号,避免重复发单)
    context.last_signal = 0   # 0:无信号, 1:金叉(做多), -1:死叉(做空)

# -------------------- 核心策略函数 --------------------
def handle_data(context):
    # 获取日线收盘价数据(numpy数组)
    close = Close()
    
    # 检查数据长度是否足够
    if len(close) < context.slow_period + 1:
        LogInfo("数据不足,等待...")
        return
    
    # 计算5日和20日简单移动平均线
    ma_fast = talib.SMA(close, context.fast_period)
    ma_slow = talib.SMA(close, context.slow_period)
    
    # 获取当前最新值
    current_ma_fast = ma_fast[-1]
    current_ma_slow = ma_slow[-1]
    prev_ma_fast = ma_fast[-2]
    prev_ma_slow = ma_slow[-2]
    current_close = close[-1]
    
    # ========== 绘制均线到K线图(新增部分)==========
    # PlotNumeric(名称, 数值, 颜色, 是否主图)
    # 第4个参数为False表示绘制在主图上(与K线叠加)[reference:1]
    PlotNumeric("MA5", current_ma_fast, RGB_Red(), False)      # 红色5日均线
    PlotNumeric("MA20", current_ma_slow, RGB_Blue(), False)    # 蓝色20日均线
    # ================================================
    
    # 判断金叉和死叉
    # 金叉:今日快线 > 慢线 且 昨日快线 <= 慢线
    golden_cross = (current_ma_fast > current_ma_slow) and (prev_ma_fast <= prev_ma_slow)
    # 死叉:今日快线 < 慢线 且 昨日快线 >= 慢线
    dead_cross = (current_ma_fast < current_ma_slow) and (prev_ma_fast >= prev_ma_slow)
    
    # 获取当前持仓状态
    pos = MarketPosition()  # 1:多头, -1:空头, 0:无持仓
    
    # -------------------- 交易逻辑 --------------------
    
    # 【金叉做多】5日均线上穿20日均线
    if golden_cross and pos <= 0:
        qty = 1
        Buy(qty, current_close)
        LogInfo("【金叉】5日均线(%.2f)上穿20日均线(%.2f),开多仓1手,价格:%.2f" % 
                (current_ma_fast, current_ma_slow, current_close))
        context.last_signal = 1
    
    # 【死叉做空】5日均线下穿20日均线
    elif dead_cross and pos >= 0:
        qty = 1
        SellShort(qty, current_close)
        LogInfo("【死叉】5日均线(%.2f)下穿20日均线(%.2f),开空仓1手,价格:%.2f" % 
                (current_ma_fast, current_ma_slow, current_close))
        context.last_signal = -1

核对:

发现有差异:
原来是:

核心结论

回测阶段:无论代码中设置 SetOrderWay(1) 还是 SetOrderWay(2),发单方式统一为"K线稳定后发单",即当前K线走完后触发。

实盘阶段:SetOrderWay(2) 才真正生效——等K线走完、下一根K线开始时才发单。

如果您希望在回测中模拟实盘"K线稳定后发单"的延迟效果(即信号日次日开盘才成交),可以使用以下方式:

# 在 handle_data 中使用延迟发单
# 用全局变量记录信号,延迟一根Bar执行

def initialize(context):
    context.pending_signal = 0  # 0:无, 1:做多, -1:做空
    context.signal_price = 0.0

def handle_data(context):
    # ... 计算均线和判断金叉死叉 ...
    
    # 如果上一根Bar有信号,现在执行
    if context.pending_signal == 1 and pos <= 0:
        Buy(1, open[-1])  # 以今日开盘价成交
        context.pending_signal = 0
    elif context.pending_signal == -1 and pos >= 0:
        SellShort(1, open[-1])
        context.pending_signal = 0
    
    # 当前Bar产生新信号,记录到下一根执行
    if golden_cross:
        context.pending_signal = 1
        context.signal_price = close[-1]
    elif dead_cross:
        context.pending_signal = -1
        context.signal_price = close[-1]

这样再和快期3的k线图对比,基本上就可以对得上了(差1个点或者2个点)

二、沪铜

三、豆粕

暧昧帖

本文暂无标签