//========================================================================
//  EXPMA金叉死叉 + 吊灯出场 + 固定止损 · 一次性执行(手动指定方向)
//  TBQuant(开拓者) 麦语言版 —— 与 pythongo 版逻辑一致
//
//  用法:启动前设“本次方向”TradeDir(1做多等金叉 / -1做空等死叉)及参数;
//        启动后等指定方向的交叉进场,进场后用“吊灯线”与“固定止损”中更紧
//        的一条保护,触价即平;反向交叉兜底平仓;平仓后不再进场(一次性)。
//
//  ★成交口径:入场用 Buy(Lots,Close) = 信号K线收盘价成交(与 M1_zt_v3 一致);
//    请在策略属性里把“计算/成交”设为收盘价成交,以对齐该口径。
//========================================================================

Params
    Numeric TradeDir(1);      // 本次方向: 1=做多(等金叉)  -1=做空(等死叉)
    Numeric FastLen(21);      // EXPMA 快线周期
    Numeric SlowLen(42);      // EXPMA 慢线周期
    Numeric ATRLen(20);       // ATR 窗口
    Numeric K(2.5);           // 吊灯 ATR 倍数
    Numeric MaxLoss(15);      // 固定止损点数(0=关闭,只用吊灯)
    Numeric Lots(1);          // 开仓手数

Vars
    Numeric fastMA;
    Numeric slowMA;
    Numeric atrVal;
    Numeric extreme(0);       // 多:进场后最高价 / 空:进场后最低价
    Numeric chandLine;        // 吊灯线
    Numeric fixedLine;        // 固定止损线
    Numeric stopLine(0);      // 实际生效止损线(取更紧者)
    Bool    golden;
    Bool    death;
    Bool    Done(False);      // 一次性完成:平仓后不再进场
    Numeric prevPos(0);       // 上一根的持仓方向

Begin
    //---------- 指标 ----------
    fastMA = XAverage(Close, FastLen);
    slowMA = XAverage(Close, SlowLen);
    atrVal = AvgTrueRange(ATRLen);

    //---------- 金叉/死叉(已收线的当前值 vs 前一根) ----------
    golden = (fastMA[1] <= slowMA[1]) And (fastMA > slowMA);
    death  = (fastMA[1] >= slowMA[1]) And (fastMA < slowMA);

    //---------- 一次性完成检测:上一根有仓、本根空仓 => 已平仓 ----------
    If (prevPos <> 0 And MarketPosition == 0) Then Done = True;

    //---------- 进场:空仓且未完成,只做指定方向 ----------
    If (MarketPosition == 0 And Done == False) Then
    Begin
        If (TradeDir == 1  And golden) Then Buy(Lots, Close);        // 金叉开多
        If (TradeDir == -1 And death)  Then SellShort(Lots, Close);  // 死叉开空
    End

    //---------- 持多管理:吊灯 + 固定止损(取更紧),反向交叉兜底 ----------
    If (MarketPosition == 1) Then
    Begin
        If (BarsSinceEntry == 0) Then extreme = High
        Else extreme = Max(extreme, High);

        chandLine = extreme - K * atrVal;
        If (MaxLoss > 0) Then fixedLine = AvgEntryPrice - MaxLoss
        Else fixedLine = -1000000;
        stopLine = Max(chandLine, fixedLine);       // 多单取更高(更紧)的那条

        If (death) Then
            Sell(Lots, Close)                        // 死叉优先:收盘价平多
        Else
            Sell(Lots, stopLine);                    // 否则挂/更新吊灯止损,触价平多
    End

    //---------- 持空管理:对称 ----------
    If (MarketPosition == -1) Then
    Begin
        If (BarsSinceEntry == 0) Then extreme = Low
        Else extreme = Min(extreme, Low);

        chandLine = extreme + K * atrVal;
        If (MaxLoss > 0) Then fixedLine = AvgEntryPrice + MaxLoss
        Else fixedLine = 1000000;
        stopLine = Min(chandLine, fixedLine);        // 空单取更低(更紧)的那条

        If (golden) Then
            BuyToCover(Lots, Close)                  // 金叉优先:收盘价平空
        Else
            BuyToCover(Lots, stopLine);              // 否则挂/更新吊灯止损,触价平空
    End

    //---------- 记录本根持仓,供下一根做完成检测 ----------
    prevPos = MarketPosition;
End

//========================================================================
//  说明 / 可能需要按你的 TBQuant 版本微调之处:
//  1. 入场成交口径:Buy(Lots,Close) 按信号K线收盘价成交,请在策略属性里
//     选“收盘价成交/K线走完后计算”,与 M1_zt_v3 对齐。
//  2. 止损单 Sell(Lots, stopLine):TB 会把低于市价的卖单作为触价(止损)
//     单,盘中价格触及即成交、每根按新 stopLine 更新(即移动止损)。
//     若你的版本要求显式 Stop 关键字(如 Sell Next Bar at stopLine Stop),
//     编译报错时把错误发我,我改成对应写法。
//  3. XAverage=EXPMA、AvgTrueRange=ATR、AvgEntryPrice=持仓均价、
//     BarsSinceEntry=进场以来K线数、MarketPosition=持仓方向,均为TB内置。
//  4. 一次性:Done 置True后不再进场;要下一单,手动重启/重挂该策略实例。
//========================================================================
