【多策略调整与优化】

易斋易斋··303 浏览

一、整体功能总结

我的这个策略是面向期货(贵金属品种)的自动化交易策略,基于1分钟K线行情,实现“轮换合约+阴阳线开仓+5分钟定时平仓”的完整交易逻辑。

二、逐模块详细解释

1. 导入依赖(代码开头)
from datetime import datetime
import panda_quant
from panda_backtest.api.future_api import future_api_quotation  # 获取期货行情数据
from panda_trading.trading_common.api.api import target_future_group_order, buy_open, sell_open, buy_close, sell_close  # 期货下单函数
from panda_trading import SRLogger  # 日志工具
  • datetime:处理时间相关逻辑(如计算持仓时长、获取当前时间);
  • panda_quant:量化框架核心库;
  • future_api_quotation:获取期货合约的K线行情数据(如1分钟线);
  • 下单函数:
    • buy_open:买入开多(建立多头持仓);
    • sell_open:卖出开空(建立空头持仓);
    • buy_close:买入平空(平掉空头持仓);
    • sell_close:卖出平多(平掉多头持仓);
  • SRLogger:框架日志工具,用于记录策略运行信息(比print更规范)。
2. 合约列表定义
SYMBOLS = [
    "AG2604.SHF",   
    "AU2604.SHF",   
    "AG2605.SHF",  
    "AU2605.SHF",  
    "AG_DOMINANT.SHF" (便于跟踪主力合约)
]
  • 定义5个待交易的贵金属合约,后续按“分钟数取模”轮换交易(0分交易第一个、1分第二个、5分回到第一个)。
3. 框架生命周期函数(核心)

量化框架会按“初始化→交易前→行情推送(handle_data)→交易后”的顺序执行函数,核心逻辑在handle_data中。

(1) 初始化函数(initialize)
def initialize(context):
    SRLogger.info("initialize")  # 记录初始化日志
    SRLogger.info('context.now: ' + str(context.now))  # 打印框架上下文的当前时间(回测/实盘时间)
    now = datetime.now()  # 获取本地系统时间
    print('时间', now)
  • 策略启动时执行一次,用于初始化全局变量、打印启动日志;
  • 注意:datetime.now()本地系统时间,回测或可改用context.now
  • (2) 交易前函数(before_trading)
def before_trading(context):
    SRLogger.info("before_trading")
  • 每日交易开始前执行,当前仅打印日志,可扩展:如初始化当日参数、查询账户资金等。
(3) 核心交易逻辑(handle_data)

每次行情数据推送时执行(如1分钟推送一次),是策略的核心:

def handle_data(context, data):
    SRLogger.info("handle_data")
    account = context.run_info.future_account  # 获取交易账户信息

    # 1. 按分钟轮换合约:当前分钟数 % 合约数量 = 选中合约索引
    now = datetime.now()
    print('时间', now)
    idx = now.minute % len(SYMBOLS)
    symbol = SYMBOLS[idx]
    SRLogger.info(f"当前分钟: {now.minute}, 选择合约: {symbol}")

    # 2. 获取行情数据:上一交易日到当日的1分钟K线
    today_str = datetime.now().strftime('%Y%m%d')
    start_date = panda_quant.get_previous_trading_date(today_str)  # 上一交易日
    end_date = today_str
    SRLogger.info(f"调用参数: symbol_list={[symbol]}, start_date={start_date}, end_date={end_date}, period='1m'")
    quotation_df_1m = future_api_quotation(symbol_list=[symbol], start_date=start_date, end_date=end_date, period='1m')
    SRLogger.info(quotation_df_1m)

    # 3. 数据校验:至少需要2根K线(才能取前一根判断阴阳)
    if quotation_df_1m is None or len(quotation_df_1m) < 2:
        SRLogger.info(f"合约 {symbol} 的1分钟数据不足以判断K线阴阳")
        return

    # 4. 排序K线:确保按时间从早到晚排列,取倒数第二根(前一根)K线
    if "time" in quotation_df_1m.columns:
        quotation_df_1m = quotation_df_1m.sort_values(by=["date", "time"])
    else:
        quotation_df_1m = quotation_df_1m.sort_values(by=["date"])
    prev_bar = quotation_df_1m.iloc[-2]  # 前一根1分钟K线(排除最新未收盘的)
    open_price = float(prev_bar["open"])  # 开盘价
    close_price = float(prev_bar["close"])  # 收盘价

    # 5. 查询持仓:获取该合约的多头/空头持仓数量
    position = context.future_account_dict[account].positions.get(symbol)
    if position is None:
        long_quantity = 0  # 多头持仓数
        short_quantity = 0  # 空头持仓数
    else:
        long_quantity = position.buy_quantity
        short_quantity = position.sell_quantity

    # 6. 开仓逻辑:无持仓时,阳线开多、阴线开空、十字线不操作
    if long_quantity == 0 and short_quantity == 0:
        if close_price > open_price:  # 阳线(收盘价>开盘价)
            buy_open(account, symbol, 1)  # 买入开多1手
            SRLogger.info(f"前一分钟K线为阳线(开={open_price}, 收={close_price}),无多空持仓,买入开多 {symbol}")
            # 记录开仓状态(方向+时间)
            context.trade_state = getattr(context, "trade_state", {})
            context.trade_state[symbol] = {"side": "long", "open_minute": now}
        elif close_price < open_price:  # 阴线(收盘价<开盘价)
            sell_open(account, symbol, 1)  # 卖出开空1手
            SRLogger.info(f"前一分钟K线为阴线(开={open_price}, 收={close_price}),无多空持仓,卖出开空 {symbol}")
            # 记录开仓状态
            context.trade_state = getattr(context, "trade_state", {})
            context.trade_state[symbol] = {"side": "short", "open_minute": now}
        else:  # 十字线(收盘价=开盘价)
            SRLogger.info(f"前一分钟K线为十字线(开={open_price}, 收={close_price}),无多空持仓,不开仓 {symbol}")
            return

    # 7. 平仓逻辑:持仓满5分钟则平仓
    else:
        context.trade_state = getattr(context, "trade_state", {})
        state = context.trade_state.get(symbol, None)
        if state is None:
            return
        open_minute = state.get("open_minute")
        side = state.get("side")

        # 计算持仓时长(分钟)
        if isinstance(open_minute, datetime):
            held_minutes = (now - open_minute).total_seconds() / 60.0
        else:
            SRLogger.info(f"开仓时间记录异常,无法计算持仓时间: {open_minute}")
            return

        # 持仓满5分钟,对应平仓
        if held_minutes >= 5:
            if side == "long" and long_quantity > 0:
                sell_close(account, symbol, long_quantity)  # 卖平多头
                SRLogger.info(f"多头持仓已满5分钟,平仓 {symbol},数量={long_quantity}")
            elif side == "short" and short_quantity > 0:
                buy_close(account, symbol, short_quantity)  # 买平空头
                SRLogger.info(f"空头持仓已满5分钟,平仓 {symbol},数量={short_quantity}")
            # 清除该合约的开仓记录
            context.trade_state.pop(symbol, None)
(4) 交易后函数(after_trading)
def after_trading(context):
    SRLogger.info("after_trading")
  • 每日交易结束后执行,当前仅打印日志,可扩展:如统计当日盈亏、持仓情况等。

评论

还没有评论,来说点什么吧
0 / 2000