#!/usr/bin/env python3
"""
在容器内调用API执行回测
"""

import json
import requests

# 读取策略代码
strategy_code = """
"""单票固定比例止损策略 - vnpy CTA回测

策略逻辑：
- 标的：沪深300ETF (510300.SSE)
- 简单均线趋势跟踪：金叉开多，死叉平多
- 开多后，如果价格从开仓价下跌超过X%，立即止损平仓
- 测试不同止损比例对策略绩效的影响

回测目标：验证不同止损比例对胜率、盈亏比、最大回撤的影响
"""

from vnpy_ctastrategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
)
from vnpy.trader.constant import Direction, Offset


class SingleStockStopLossStrategy(CtaTemplate):
    """单票固定比例止损策略 - 均线趋势跟踪+固定比例止损"""
    
    author = "关羽 (云长)"
    
    # 策略参数
    fast_window = 5    # 短期均线窗口
    slow_window = 20   # 长期均线窗口
    stop_loss_pct = 0.15  # 止损比例，亏损超过这个比例止损
    
    # 参数列表
    parameters = ["fast_window", "slow_window", "stop_loss_pct"]
    
    # 变量列表
    variables = ["fast_ma", "slow_ma", "cost_price", "in_position"]
    
    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """初始化"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        
        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager(max(self.slow_window + 10, 100))
        
        # 均线数值
        self.fast_ma = 0.0
        self.slow_ma = 0.0
        
        # 开仓成本
        self.cost_price = 0.0
        
        # 是否持仓
        self.in_position = False
        
    def on_init(self):
        """初始化策略"""
        self.write_log(f"策略初始化，fast={self.fast_window}, slow={self.slow_window}, stop_loss={self.stop_loss_pct:.1%}")
        self.put_event()
        
    def on_start(self):
        """启动策略"""
        self.put_event()
        
    def on_stop(self):
        """停止策略"""
        self.put_event()
        
    def on_bar(self, bar):
        """K线更新"""
        self.am.update_bar(bar)
        
        if not self.am.inited:
            return
        
        # 计算均线
        self.fast_ma = self.am.sma(self.fast_window)
        self.slow_ma = self.am.sma(self.slow_window)
        
        # 检查止损（只有持仓时才检查）
        have_signal = True
        if self.in_position and self.cost_price > 0:
            current_drawdown = (bar.close_price - self.cost_price) / self.cost_price
            
            if current_drawdown <= -self.stop_loss_pct:
                # 触发止损，全部平仓
                if self.pos > 0:
                    self.sell(bar.close_price, self.pos)
                    self.in_position = False
                    self.write_log(f"🔴 触发止损：成本{self.cost_price:.2f}，当前{bar.close_price:.2f}，回撤{current_drawdown:.1%}，止损卖出")
                have_signal = False
        
        # 如果没有触发止损，继续处理信号
        if have_signal:
            # 均线金叉死叉信号
            if not self.in_position:
                # 金叉：短期上穿长期，开多
                if self.fast_ma > self.slow_ma:
                    self.buy(bar.close_price, 1)  # 1手
                    self.cost_price = bar.close_price
                    self.in_position = True
                    self.write_log(f"🟢 金叉开多：价格{bar.close_price:.2f}，均线fast{self.fast_ma:.2f} slow{self.slow_ma:.2f}")
            else:
                # 死叉：短期下穿长期，平多
                if self.fast_ma < self.slow_ma:
                    if self.pos > 0:
                        self.sell(bar.close_price, self.pos)
                        self.in_position = False
                        self.write_log(f"🔵 死叉平仓：价格{bar.close_price:.2f}，均线fast{self.fast_ma:.2f} slow{self.slow_ma:.2f}")
        
        self.put_event()
        
    def on_trade(self, trade):
        """交易成交回调"""
        self.put_event()
        
    def on_order(self, order):
        """订单回调"""
        self.put_event()
        
    def on_stop_order(self, stop_order):
        """停止单回调"""
        self.put_event()
"""

request_data = {
    'strategy_code': strategy_code,
    'symbol': '510300.SSE',
    'interval': '1d',
    'start': 1609459200,
    'end': 1772515200,
    'capital': 1000000,
    'rate': 3e-5,
    'slippage': 0.002,
    'size': 10000,
    'pricetick': 0.001,
    'data_source': 'sqlite'
}

response = requests.post('http://127.0.0.1:8088/api/backtest/run', json=request_data, timeout=300)
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
