一、整体功能总结
我的这个策略是面向期货(贵金属品种)的自动化交易策略,基于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)
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")
- 每日交易结束后执行,当前仅打印日志,可扩展:如统计当日盈亏、持仓情况等。