1
关注
100
关注者

基于量化指标的蜡烛情绪动量趋势交易策略

创建于: 2025-02-25 10:22:26, 更新于: 2025-02-27 20:16:09
comments   0
hits   39

基于量化指标的蜡烛情绪动量趋势交易策略

蜡烛图是期货市场中最重要的图形分析工具之一,每根蜡烛代表了一定时间段的市场活动。通过识别不同的蜡烛图形,我们可以推测出市场的情绪变化,从而制定相应的交易策略。基于这些蜡烛图形及其组合,结合量化指标来衡量市场的情绪波动(例如贪婪、恐惧和犹豫),形成一种动量趋势交易策略。这篇文章将通过蜡烛图形、各个量化指标的功能以及具体的开平仓逻辑来帮助您理解这个策略。

一、蜡烛图形的含义与市场作用

  1. Doji (十字星)
    Doji形态是指蜡烛的开盘价和收盘价几乎相同,蜡烛实体很小,上下影线较长。它代表市场处于犹豫状态,买卖双方的力量接近平衡。
    作用: 在期货市场中,Doji通常出现在反转趋势的关键位置,标志着可能的趋势反转。 市场悄悄话:”现在多空打成平手,大家都很迷茫啊!”

  2. Spinning Top (纺锤线)
    旋转顶形态类似Doji,实体较小,但较Doji要大一些。它表示市场的犹豫不决,通常预示着震荡或短期的反转。
    作用: 在上涨或下跌趋势中出现,常常意味着短期内价格波动会减弱。 市场悄悄话:”买卖双方在拔河,胜负难分!”

  3. Shooting Star (射击之星)
    射击之星是一根上影线非常长的蜡烛,实体较小,且下影线短。通常出现在上升趋势中,预示市场情绪转为看空。
    作用: 在期货市场中,射击之星意味着买方失去控制,卖方可能即将主导市场。 期货作用:期货夜盘常见,特别是当大宗商品突发消息时。

  4. Hanging Man (吊颈线)
    吊人线和射击之星形态类似,但出现在下跌趋势的末端。它表示市场可能出现反弹,买方即将占上风。
    作用: 吊人线在下跌趋势中出现时,暗示市场可能会在此处找到支撑并反弹。 市场悄悄话:”看着涨得欢,其实有人在偷偷出货!”

  5. Engulfing (吞没形态)
    吞没形态是一种强烈的反转信号,其中后一根蜡烛完全吞没前一根蜡烛的实体。看涨吞没通常预示着多头反攻的开始,而看跌吞没则表明空头力量加强。
    作用: 吞没形态经常出现在大幅度的价格反转点。 市场悄悄话:”多头/空头发起总攻了!”

  6. Marubozu (光头光脚)
    Marubozu是一种没有上影线或下影线的蜡烛,表示强烈的市场情绪。它通常表示买方或卖方力量强劲。
    作用: 出现Marubozu时,表明市场情绪较为极端,可能会继续沿着当前趋势发展。 市场悄悄话:”多头/空头完全掌控局面!”

  7. Hammer (锤子线)
    锤子线是一种下影线很长的蜡烛,实体较小,且接近价格区间的上部。它出现在下跌趋势末端,通常预示着市场可能会反弹。
    作用: 锤子线通常意味着市场将出现反转或止跌,尤其是在低点区域。 市场悄悄话:”价格被打压后强势反弹!”

  8. Three White Soldiers (三只白兵)
    三只白兵是一种由三根连续上涨的蜡烛组成的形态,且每根蜡烛都比前一根大。它表明市场在强劲的多头推动下上涨。
    作用: 这是一种非常强烈的上涨信号,表明市场很可能会继续上涨。 市场悄悄话:“多头力量不断积聚,市场准备继续上涨!”

二、蜡烛情绪动量指标的代码与解释

本策略基于三种情绪震荡指标:犹豫震荡指标(Indecision Oscillator)恐惧震荡指标(Fear Oscillator)贪婪震荡指标(Greed Oscillator),这些指标通过识别不同的蜡烛图形来衡量市场情绪的变化。

1. Indecision Oscillator (犹豫震荡指标)

该指标通过识别DojiSpinning Top来衡量市场的犹豫不决。

// 检测是否为Doji(十字星)形态
isDoji(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)   // 计算实体大小(开盘价与收盘价的差值)
    rangeSize = high - low             // 计算蜡烛的总范围(最高价与最低价的差值)
    bodySize / rangeSize < threshold   // 如果实体占总范围的比值小于阈值,则认为是Doji

// 检测是否为旋转顶形态(Spinning Top)
isSpinningTop(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    // 旋转顶要求实体占总范围的比值小于阈值,并且大于Doji阈值
    bodySize / rangeSize < threshold and bodySize / rangeSize >= dojiThreshold

// 计算犹豫震荡指标
indecisionOscillator() =>
    var float dojiScore = 0.0   // 初始化Doji形态的得分
    var float spinningTopScore = 0.0   // 初始化旋转顶的得分
    for i = 1 to length
        if isDoji(open[i], close[i], high[i], low[i], dojiThreshold)   // 检查Doji形态
            dojiScore := dojiScore + 1.0
        if isSpinningTop(open[i], close[i], high[i], low[i], spinningTopThreshold)   // 检查旋转顶形态
            spinningTopScore := spinningTopScore + 1.0
    dojiScore := dojiScore / length   // 计算Doji形态的得分比例
    spinningTopScore := spinningTopScore / length   // 计算旋转顶的得分比例
    (dojiScore + spinningTopScore) / 2   // 返回两个形态的平均得分,作为犹豫震荡指标的结果

功能: 用于检测市场是否处于犹豫状态。通过识别Doji和旋转顶形态,来计算市场情绪的波动。

2. Fear Oscillator (恐惧震荡指标)

该指标通过识别Shooting StarHanging ManBearish Engulfing形态来衡量市场的恐惧情绪。

// 检测是否为射击之星
isShootingStar(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)   // 计算蜡烛的实体大小
    upperWick = high - math.max(open, close)  // 上影线大小
    lowerWick = math.min(open, close) - low  // 下影线大小
    upperWick / bodySize > threshold and lowerWick < bodySize   // 上影线大且下影线小,符合射击之星条件

// 检测是否为吊颈线
isHangingMan(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    lowerWick / bodySize > threshold and upperWick < bodySize   // 下影线大,上影线小,符合吊人线条件

// 检测是否为看跌吞没形态
isBearishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)   // 当前蜡烛的实体大小
    prevBodySize = math.abs(closePrev - openPrev)   // 前一根蜡烛的实体大小
    close < openPrev and open > closePrev and bodySize / prevBodySize > threshold  // 当前蜡烛吞没前一根蜡烛并且实体大小更大

// 计算恐惧震荡指标
fearOscillator() =>
    var float shootingStarScore = 0.0   // 初始化射击之星得分
    var float hangingManScore = 0.0     // 初始化吊人线得分
    var float engulfingScore = 0.0      // 初始化看跌吞没得分
    for i = 1 to length
        if isShootingStar(open[i], close[i], high[i], low[i], shootingStarThreshold)  // 检查射击之星
            shootingStarScore := shootingStarScore + 1.0
        if isHangingMan(open[i], close[i], high[i], low[i], hangingManThreshold)  // 检查吊颈线
            hangingManScore := hangingManScore + 1.0
        if isBearishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)  // 检查看跌吞没
            engulfingScore := engulfingScore + 1.0
    shootingStarScore := shootingStarScore / length   // 计算射击之星的得分比例
    hangingManScore := hangingManScore / length   // 计算吊人线的得分比例
    engulfingScore := engulfingScore / length   // 计算看跌吞没的得分比例
    (shootingStarScore + hangingManScore + engulfingScore) / 3   // 返回恐惧震荡指标的平均值

功能: 用于评估市场恐惧情绪的强度,基于射击之星、吊颈线和看跌吞没形态的频率。

3. Greed Oscillator (贪婪震荡指标)

该指标通过识别MarubozuHammerBullish EngulfingThree White Soldiers形态来衡量市场的贪婪情绪。

// 检测是否为Marubozu(光头光脚)
isMarubozu(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)   // 计算实体大小
    totalRange = high - low            // 计算蜡烛的总范围
    bodySize / totalRange > threshold   // 实体占总范围的比例大,表示为Marubozu形态

// 检测是否为锤子线
isHammer(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    lowerWick = math.min(open, close) - low
    upperWick = high - math.max(open, close)
    lowerWick / bodySize > threshold and upperWick < bodySize  // 下影线大,符合锤子线的特征

// 检测是否为看涨吞没
isBullishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close > openPrev and open < closePrev and bodySize / prevBodySize > threshold  // 当前蜡烛吞没前一根蜡烛,符合看涨吞没的条件

// 检测是否为三只白兵
isThreeWhiteSoldiers(open, close, openPrev, closePrev, openPrev2, closePrev2, threshold) =>
    close > open and closePrev > openPrev and closePrev2 > openPrev2 and close > closePrev and closePrev > closePrev2   // 连续三根上涨蜡烛,符合三只白兵形态

// 计算贪婪震荡指标
greedOscillator() =>
    var float marubozuScore = 0.0   // 初始化光头光脚得分
    var float hammerScore = 0.0     // 初始化锤子线得分
    var float engulfingScore = 0.0  // 初始化看涨吞没得分
    var float soldiersScore = 0.0   // 初始化三只白兵得分
    for i = 1 to length
        if isMarubozu(open[i], close[i], high[i], low[i], marubozuThreshold)  // 检查光头光脚
            marubozuScore := marubozuScore + 1.0
        if isHammer(open[i], close[i], high[i], low[i], hammerThreshold)  // 检查锤子线
            hammerScore := hammerScore + 1.0
        if isBullishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)  // 检查看涨吞没
            engulfingScore := engulfingScore + 1.0
        if isThreeWhiteSoldiers(open[i], close[i], open[i+1], close[i+1], open[i+2], close[i+2], threeWhiteSoldiersThreshold)  // 检查三只白兵
            soldiersScore := soldiersScore + 1.0
    marubozuScore := marubozuScore / length   // 计算光头光脚的得分比例
    hammerScore := hammerScore / length   // 计算锤子线的得分比例
    engulfingScore := engulfingScore / length   // 计算看涨吞没的得分比例
    soldiersScore := soldiersScore / length   // 计算三只白兵的得分比例
    (marubozuScore + hammerScore + engulfingScore + soldiersScore) / 4   // 返回贪婪震荡指标的平均值

功能: 用于评估市场的贪婪情绪,通过检测强势的上涨信号(如Marubozu、锤子线等)来衡量市场的买盘压力。

三、开平仓逻辑

情绪指数三剑客
1. 犹豫指数:十字星+纺锤线,数值越高市场越像迷路的小孩
2. 恐慌指数:流星线+吊颈线+看跌吞噬,空头司令部集结号
3. 贪婪指数:光头线+锤子线+看涨吞噬,多头狂欢派对

当三个指数调和出的鸡尾酒浓度超过设定值:
- 做多信号:鸡尾酒浓度突破10%(可调节)
- 做空信号:鸡尾酒浓度突破20%(可调节)

风控三保险
1. 成交量认证:平仓时需要成交量是均量的1.5倍(可调节),避免假突破
2. 最长持仓时间:盈利单最多拿20根K线(约4个交易日)
3. 紧急逃生舱:亏损超2%或持仓10根K线仍亏损,强制止损

  1. 买入信号(Long Entry)

    • averageOscillator(三个震荡指标的平均值)上穿0.1时,表示市场情绪转为多头,发出买入信号。
    • 若没有持仓且冷却期已过,则开仓多头。
  2. 卖出信号(Take Profit / Stop Loss)

    • 当价格上涨并且成交量高于一定阈值时,满足卖出条件,执行平仓操作。
    • 若持仓时间超过最大持仓期,或亏损达到设定阈值(例如10%),则平仓。
  3. 空仓信号(Short Entry)

    • averageOscillator上穿0.2时,表示市场情绪转为空头,发出卖空信号。
    • 若没有持仓且冷却期已过,则开空仓。
  4. 空头平仓信号

    • 当满足特定卖出条件(如价格下跌且成交量增加)时,执行空头平仓。

四、策略结果验证

基于量化指标的蜡烛情绪动量趋势交易策略 基于量化指标的蜡烛情绪动量趋势交易策略

通过这些蜡烛图形和情绪动量指标的结合,本策略旨在捕捉市场的情绪变化,制定合适的买卖决策,从而实现较为稳定的收益。

五、完整策略源码

//@version=6
strategy("Candle Emotion Index Strategy", shorttitle="CEI Strategy", overlay=true)

// 用户输入参数
length = input.int(14, title="回看周期", minval=1)  // 设置回看周期,默认为14
dojiThreshold = input.float(0.1, title="Doji 阈值", minval=0.01, maxval=0.5)  // 设置Doji形态的阈值
spinningTopThreshold = input.float(0.3, title="旋转顶阈值", minval=0.1, maxval=0.5)  // 设置旋转顶形态的阈值
shootingStarThreshold = input.float(0.5, title="射击之星阈值", minval=0.1, maxval=1.0)  // 设置射击之星形态的阈值
hangingManThreshold = input.float(0.5, title="吊人线阈值", minval=0.1, maxval=1.0)  // 设置吊人线形态的阈值
engulfingThreshold = input.float(0.5, title="吞没形态阈值", minval=0.1, maxval=1.0)  // 设置吞没形态的阈值
marubozuThreshold = input.float(0.9, title="光头光脚阈值", minval=0.5, maxval=1.0)  // 设置光头光脚形态的阈值
hammerThreshold = input.float(0.5, title="锤子线阈值", minval=0.1, maxval=1.0)  // 设置锤子线形态的阈值
threeWhiteSoldiersThreshold = input.float(0.5, title="三只白兵阈值", minval=0.1, maxval=1.0)  // 设置三只白兵形态的阈值

// 成交量倍数
volumeMultiplier = input.float(1.5, title="成交量倍数", minval=1.0)  // 设置成交量倍数,用于平仓的条件判断

// 冷却期输入
cooldownPeriod = input.int(10, title="冷却期(蜡烛数)", minval=1)  // 设置冷却期,表示每次交易后等待冷却的蜡烛数

// 最大持仓周期输入
maxHoldingPeriod = input.int(20, title="最大持仓周期(蜡烛数)", minval=1)  // 设置最大持仓周期,限制持仓时间
lossHoldingPeriod = input.int(10, title="亏损退出持仓周期(蜡烛数)", minval=1)  // 设置亏损退出持仓的最大周期
lossThreshold = input.float(0.02, title="亏损阈值(相对于开盘价的百分比)", minval=0.01, maxval=1.0)  // 设置亏损阈值,当亏损达到此百分比时退出

// --- 犹豫震荡指标函数 ---
isDoji(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    rangeSize = high - low  // 计算蜡烛的价格区间
    bodySize / rangeSize < threshold  // 若实体占总范围的比值小于阈值,认为是Doji

isSpinningTop(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    rangeSize = high - low  // 计算蜡烛的价格区间
    bodySize / rangeSize < threshold and bodySize / rangeSize >= dojiThreshold  // 若实体占总范围的比值小于阈值,且大于Doji阈值,认为是旋转顶

indecisionOscillator() =>
    var float dojiScore = 0.0  // 初始化Doji形态的得分
    var float spinningTopScore = 0.0  // 初始化旋转顶形态的得分
    for i = 1 to length
        if isDoji(open[i], close[i], high[i], low[i], dojiThreshold)  // 检测Doji形态
            dojiScore := dojiScore + 1.0
        if isSpinningTop(open[i], close[i], high[i], low[i], spinningTopThreshold)  // 检测旋转顶形态
            spinningTopScore := spinningTopScore + 1.0
    dojiScore := dojiScore / length  // 计算Doji形态得分的平均值
    spinningTopScore := spinningTopScore / length  // 计算旋转顶形态得分的平均值
    (dojiScore + spinningTopScore) / 2  // 返回犹豫震荡指标的平均得分

// --- 恐惧震荡指标函数 ---
isShootingStar(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    upperWick = high - math.max(open, close)  // 计算上影线长度
    lowerWick = math.min(open, close) - low  // 计算下影线长度
    upperWick / bodySize > threshold and lowerWick < bodySize  // 上影线较长且下影线较短,符合射击之星条件

isHangingMan(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    upperWick = high - math.max(open, close)  // 计算上影线长度
    lowerWick = math.min(open, close) - low  // 计算下影线长度
    lowerWick / bodySize > threshold and upperWick < bodySize  // 下影线较长且上影线较短,符合吊人线条件

isBearishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)  // 当前蜡烛的实体大小
    prevBodySize = math.abs(closePrev - openPrev)  // 前一根蜡烛的实体大小
    close < openPrev and open > closePrev and bodySize / prevBodySize > threshold  // 当前蜡烛吞没前一根蜡烛,且实体大小更大

fearOscillator() =>
    var float shootingStarScore = 0.0  // 初始化射击之星得分
    var float hangingManScore = 0.0  // 初始化吊人线得分
    var float engulfingScore = 0.0  // 初始化看跌吞没得分
    for i = 1 to length
        if isShootingStar(open[i], close[i], high[i], low[i], shootingStarThreshold)  // 检测射击之星
            shootingStarScore := shootingStarScore + 1.0
        if isHangingMan(open[i], close[i], high[i], low[i], hangingManThreshold)  // 检测吊人线
            hangingManScore := hangingManScore + 1.0
        if isBearishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)  // 检测看跌吞没
            engulfingScore := engulfingScore + 1.0
    shootingStarScore := shootingStarScore / length  // 计算射击之星的得分比例
    hangingManScore := hangingManScore / length  // 计算吊人线的得分比例
    engulfingScore := engulfingScore / length  // 计算看跌吞没的得分比例
    (shootingStarScore + hangingManScore + engulfingScore) / 3  // 返回恐惧震荡指标的平均得分

// --- 贪婪震荡指标函数 ---
isMarubozu(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    totalRange = high - low  // 计算蜡烛的价格区间
    bodySize / totalRange > threshold  // 实体占总范围的比例大,符合光头光脚条件

isHammer(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)  // 计算蜡烛实体大小
    lowerWick = math.min(open, close) - low  // 计算下影线长度
    upperWick = high - math.max(open, close)  // 计算上影线长度
    lowerWick / bodySize > threshold and upperWick < bodySize  // 下影线较长且上影线较短,符合锤子线条件

isBullishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)  // 当前蜡烛的实体大小
    prevBodySize = math.abs(closePrev - openPrev)  // 前一根蜡烛的实体大小
    close > openPrev and open < closePrev and bodySize / prevBodySize > threshold  // 当前蜡烛吞没前一根蜡烛,符合看涨吞没条件

isThreeWhiteSoldiers(open, close, openPrev, closePrev, openPrev2, closePrev2, threshold) =>
    close > open and closePrev > openPrev and closePrev2 > openPrev2 and close > closePrev and closePrev > closePrev2  // 连续三根上涨蜡烛,符合三只白兵条件

greedOscillator() =>
    var float marubozuScore = 0.0  // 初始化光头光脚得分
    var float hammerScore = 0.0  // 初始化锤子线得分
    var float engulfingScore = 0.0  // 初始化看涨吞没得分
    var float soldiersScore = 0.0  // 初始化三只白兵得分
    for i = 1 to length
        if isMarubozu(open[i], close[i], high[i], low[i], marubozuThreshold)  // 检查光头光脚
            marubozuScore := marubozuScore + 1.0
        if isHammer(open[i], close[i], high[i], low[i], hammerThreshold)  // 检查锤子线
            hammerScore := hammerScore + 1.0
        if isBullishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)  // 检查看涨吞没
            engulfingScore := engulfingScore + 1.0
        if isThreeWhiteSoldiers(open[i], close[i], open[i+1], close[i+1], open[i+2], close[i+2], threeWhiteSoldiersThreshold)  // 检查三只白兵
            soldiersScore := soldiersScore + 1.0
    marubozuScore := marubozuScore / length  // 计算光头光脚的得分比例
    hammerScore := hammerScore / length  // 计算锤子线的得分比例
    engulfingScore := engulfingScore / length  // 计算看涨吞没的得分比例
    soldiersScore := soldiersScore / length  // 计算三只白兵的得分比例
    (marubozuScore + hammerScore + engulfingScore + soldiersScore) / 4  // 返回贪婪震荡指标的平均得分

// --- 最终计算 ---
indecision = indecisionOscillator()  // 计算犹豫震荡指标
fear = fearOscillator()  // 计算恐惧震荡指标
greed = greedOscillator()  // 计算贪婪震荡指标

// 计算三个震荡指标的平均值
averageOscillator = (indecision + fear + greed) / 3  // 计算所有情绪指标的平均得分

// --- 组合策略逻辑 ---
var float entryPriceLong = na  // 定义多头入场价格
var float entryPriceShort = na  // 定义空头入场价格
var int holdingPeriodLong = 0  // 多头持仓周期
var int holdingPeriodShort = 0  // 空头持仓周期
var int cooldownCounter = 0  // 冷却期计数器

// 多头买入信号
longBuySignal = ta.crossover(averageOscillator, 0.1)  // 当情绪震荡指标上穿0.1时,产生多头买入信号
// 空头买入信号
shortBuySignal = ta.crossover(averageOscillator, 0.2)  // 当情绪震荡指标上穿0.2时,产生空头买入信号

// 计算回看期的平均成交量
avgVolume = ta.sma(volume, length)  // 计算回看期内的平均成交量

// 多头平仓条件
longTakeProfitCondition = close > open and volume > avgVolume * volumeMultiplier  // 如果当前价格上涨且成交量超过平均成交量的1.5倍,则平仓
// 空头平仓条件
shortTakeProfitCondition = close < open and volume > avgVolume * volumeMultiplier  // 如果当前价格下跌且成交量超过平均成交量的1.5倍,则平仓

// 多头买入逻辑
if longBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceLong := close  // 记录入场价格
    strategy.entry("Long Entry", strategy.long)  // 进场做多
    cooldownCounter := cooldownPeriod  // 进入冷却期
    holdingPeriodLong := 0  // 重置持仓周期

// 增加多头持仓周期
if strategy.position_size > 0
    holdingPeriodLong := holdingPeriodLong + 1

// 多头平仓逻辑
if longTakeProfitCondition and strategy.position_size > 0 and close > entryPriceLong  // 满足平仓条件,且当前价格高于入场价
    strategy.close_all()  // 平掉所有多头仓位
    cooldownCounter := cooldownPeriod  // 进入冷却期

// 若持仓超过最大持仓周期,平仓
if holdingPeriodLong >= maxHoldingPeriod and strategy.position_size > 0 and close >= entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// 若亏损超过阈值,平仓
if holdingPeriodLong >= lossHoldingPeriod and strategy.position_size > 0 and close < entryPriceLong * (1 - lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// 空头买入逻辑
if shortBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceShort := close  // 记录入场价格
    strategy.entry("Short Entry", strategy.short)  // 进场做空
    cooldownCounter := cooldownPeriod  // 进入冷却期
    holdingPeriodShort := 0  // 重置持仓周期

// 增加空头持仓周期
if strategy.position_size < 0
    holdingPeriodShort := holdingPeriodShort + 1

// 空头平仓逻辑
if shortTakeProfitCondition and strategy.position_size < 0 and close < entryPriceShort  // 满足平仓条件,且当前价格低于入场价
    strategy.close_all()  // 平掉所有空头仓位
    cooldownCounter := cooldownPeriod  // 进入冷却期

// 若持仓超过最大持仓周期,平仓
if holdingPeriodShort >= maxHoldingPeriod and strategy.position_size < 0 and close <= entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// 若亏损超过阈值,平仓
if holdingPeriodShort >= lossHoldingPeriod and strategy.position_size < 0 and close > entryPriceShort * (1 + lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// 每根蜡烛减少冷却期计数器
if cooldownCounter > 0
    cooldownCounter := cooldownCounter - 1
更多内容