策略分享

自动下单股指期货主力合约,按每周我提前给出的每日操作方向,在每日的10点和下午2点左右做出操作,尾盘平掉。

由bqceosk1创建,最终由bqceosk1 被浏览 1 用户

from bigmodule import M
import pandas as pd
from datetime import datetime, time

# ==========================================
# 1. 用户配置区域
# ==========================================

# 你的每周操作方向表 (格式: "YYYY-MM-DD": 方向)
# 1 = 做多, -1 = 做空, 0 = 不操作
USER_DIRECTION_MAP = {
    "2024-03-04": 1,   # 周一:做多
    "2024-03-05": -1,  # 周二:做空
    "2024-03-06": 1,   # 周三:做多
    "2024-03-07": 0,   # 周四:休息
    "2024-03-08": -1,  # 周五:做空
}

# 交易标的:沪深300股指期货 (IF)
FUTURE_CODE = "IF.CFE" 

# 交易参数
TARGET_PERCENT = 0.9  
# ==========================================


def m1_initialize_bigquant_run(context):
    """初始化函数"""
    # 设置手续费
    try:
        from bigtrader.finance.commission import PerOrder
        context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0003, min_cost=5))
    except Exception:
        pass

    # 存入上下文
    context.direction_map = USER_DIRECTION_MAP
    context.future_code = FUTURE_CODE
    context.target_pct = TARGET_PERCENT
    
    # 初始化变量
    context.trade_log = []
    context.current_pos = 0
    context.entry_price = 0

def m1_handle_data_bigquant_run(context, data):
    """每分钟运行逻辑"""
    current_time = data.current_dt.time()
    current_date_str = data.current_dt.strftime("%Y-%m-%d")
    
    # 获取合约代码
    try:
        symbol = context.symbol(context.future_code)
    except:
        symbol = context.future_code

    # 获取今日方向
    today_direction = context.direction_map.get(current_date_str, 0)

    # 获取当前价格 (优先尝试 last_price,不行再用 close)
    current_price = None
    try:
        current_price = data.current(symbol, "last_price")
        if current_price is None:
            current_price = data.current(symbol, "close")
    except:
        # 如果获取价格失败,尝试用 close 字段再试一次
        try: current_price = data.current(symbol, "close")
        except: return # 彻底无法获取价格则跳过

    if current_price is None: return

    # 获取当前持仓
    position = 0
    try:
        if hasattr(context, "portfolio"):
            pos_obj = context.portfolio.positions.get(symbol)
            if pos_obj:
                position = pos_obj.amount
    except:
        pass

    # --- 策略核心逻辑 ---

    # 1. 尾盘平仓 (14:55)
    if current_time >= time(14, 55):
        if position != 0:
            pnl = (current_price - context.entry_price) * context.current_pos
            context.trade_log.append({
                "date": current_date_str, "type": "平仓",
                "direction": "多" if context.current_pos == 1 else "空",
                "price": current_price, "pnl": pnl
            })
            try: context.order_target_percent(symbol, 0)
            except: pass
            context.current_pos = 0
            context.entry_price = 0

    # 2. 开仓逻辑 (10:00 和 14:00)
    is_opening_time = (time(10, 0) <= current_time < time(10, 1)) or (time(14, 0) <= current_time < time(14, 1))
    
    if is_opening_time and today_direction != 0 and position == 0:
        target = today_direction * context.target_pct
        try:
            context.order_target_percent(symbol, target)
            context.current_pos = today_direction
            context.entry_price = current_price
            
            context.trade_log.append({
                "date": current_date_str, "type": "开仓",
                "direction": "多" if today_direction == 1 else "空",
                "price": current_price, "pnl": 0
            })
        except Exception as e:
            print(f"下单失败: {e}")

    # 3. 盘中风控
    if today_direction == 0 and position != 0:
         try: context.order_target_percent(symbol, 0)
         except: pass
         context.current_pos = 0

    # --- 回测结束统计 ---
    if current_time >= time(14, 59) and len(context.trade_log) > 0:
        close_trades = [t for t in context.trade_log if t["type"] == "平仓"]
        if not close_trades: return

        pnls = [t["pnl"] for t in close_trades]
        total_trades = len(pnls)
        wins = [p for p in pnls if p > 0]
        losses = [p for p in pnls if p < 0]
        
        win_rate = len(wins) / total_trades
        avg_win = sum(wins) / len(wins) if wins else 0
        avg_loss = abs(sum(losses) / len(losses)) if losses else 0
        
        profit_loss_ratio = avg_win / avg_loss if avg_loss != 0 else float('inf')

        print("\n" + "="*30)
        print("📈 策略回测统计报告")
        print("="*30)
        print(f"总交易笔数: {total_trades}")
        print(f"盈利笔数: {len(wins)}")
        print(f"亏损笔数: {len(losses)}")
        print(f"胜率: {win_rate:.2%}")
        print(f"平均盈利: {avg_win:.2f}")
        print(f"平均亏损: {avg_loss:.2f}")
        print(f"盈亏比: {profit_loss_ratio:.2f}")
        print("="*30)

# ==========================================
# 2. 数据模块配置 (已修正:改用通用数据源)
# ==========================================

# 【关键修改】不再指定 expr_tables,让系统自动查找你账号里有的数据
# 使用 "auto" 模式或者仅指定字段,让平台自动匹配
m2 = M.input_features_dai.v30(
    mode="表达式",
    expr="close", 
    expr_filters="",
    # expr_tables="",  <-- 留空,让系统自动去匹配期货分钟数据
    extra_fields="date, instrument, open, high, low, volume",
    order_by="date, instrument",
    expr_drop_na=True,
    extract_data=False,
    m_name="m2"
)

# 设置回测时间范围
start_date = "2024-03-01"
end_date = "2024-03-10"

m4 = M.extract_data_dai.v20(
    sql=m2.data,
    start_date=start_date,
    start_date_bound_to_trading_date=True,
    end_date=end_date,
    end_date_bound_to_trading_date=True,
    before_start_days=0,
    keep_before=False,
    debug=False,
    m_name="m4"
)

# 启动交易引擎
m1 = M.bigtrader.v43(
    data=m4.data,
    start_date=start_date,
    end_date=end_date,
    initialize=m1_initialize_bigquant_run,
    handle_data=m1_handle_data_bigquant_run,
    capital_base=1000000,
    frequency="minute",
    product_type="期货",
    rebalance_period_type="交易日",
    rebalance_period_days="1",
    order_price_field_buy="open",
    order_price_field_sell="open",
    benchmark="沪深300指数",
    plot_charts=True,
    backtest_only=False,
    m_name="m1"
)

\

{link}