该策略结合了移动平均线判断趋势方向和K线形态判断反转点的方法,实现了趋势追踪交易。策略首先使用移动平均线判断整体趋势方向,然后在趋势方向上寻找潜在的反转K线形态作为入场信号,从而追踪趋势运行。
策略使用长度为10天的简单移动平均线判断价格趋势方向。当价格高于移动平均线时,认为处于上升趋势;当价格低于移动平均线时,认为处于下降趋势。
在判断到趋势方向后,策略会根据一系列阳线K线形态和阴线K线形态来判断潜在的趋势反转点。常见的阳线形态包括启明星、早晨之星、三只白兵等;常见的阴线形态包括黄昏之星、三只乌鸦等。当在上升趋势中识别到阳线信号时,策略会进行买入操作;当在下降趋势中识别到阴线信号时,策略会进行卖出操作。
此外,策略还会结合主要的支撑阻力位来确定入场的具体价格。如在上升趋势下买入时,会在突破第一支撑位时进行买入。
该策略最大的优势是同时结合趋势判断和反转信号,使得它可以及时捕捉趋势转折点,实现趋势跟踪运行。相比简单的移动平均线策略,该策略可以大大提高获利概率。
另外,策略加入K线形态判断也增强了其对突发事件的处理能力。在市场出现低概率事件导致假突破时,K线形态可以发挥过滤作用,避免错误交易。
该策略主要的风险在于移动平均线参数设置和K线形态判断的准确性。如果移动平均线周期设置得不当,会导致趋势判断错误;如果对K线形态判断出现失误,也会导致交易决策失误。
此外,反转K线形态并不能百分百确保趋势反转,所以策略也存在一定的风险。当市场出现更大范围的反转时,可能会给策略带来较大亏损。
该策略的优化空间还是比较大的。例如可以考虑动态调整移动平均线的参数,在不同市场阶段采用不同的移动平均线周期。还可以加入机器学习的方法,利用历史数据训练K线形态判断模型,提高判断准确性。
另外,也可以考虑加入更多因子判断趋势和热点区域,如交易量变化、波动率指标等,使策略更加全面和稳健。
该策略整体来说非常适合跟踪股市中期趋势,可以获得较高的稳定收益。如果进一步优化,有望成为一个运作良好的量化策略。投资者如果掌握该策略的运用,也可以用其构建长期持有的组合,以控制个股风险的同时获得较好的超额收益。
/*backtest start: 2024-01-01 00:00:00 end: 2024-01-31 23:59:59 period: 3h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=5 strategy("Trend Following Strategy with Candlestick Patterns", overlay=true) // Moving Average ma_period = input(10, title="Moving Average Period") moving_average = ta.sma(close, ma_period) // Candlestick Patterns // Custom Function abs(x) => x >= 0 ? x : -x // Candlestick Patterns isDoji() => (close - open) <= (high - low) * 0.1 isMarubozuWhite() => close == high and open == low and close > open isHammer() => (high - low) >= 3 * abs(open - close) and (close - low) / (0.001 + high - low) > 0.6 and (open - low) / (0.001 + high - low) > 0.6 isInvertedHammer() => (high - low) >= 3 * abs(open - close) and (high - close) / (0.001 + high - low) > 0.6 and (high - open) / (0.001 + high - low) > 0.6 isLongLowerShadow() => (low - close) > 2 * abs(open - close) and (low - open) / (0.001 + high - low) > 0.6 isUpsideTasukiGap() => close[1] < open[1] and open > close and open > close[1] and close < open[1] isRisingWindow() => high[1] < low and close > open isPiercing() => close[1] < open[1] and close > open and close > ((open + low) / 2) and close < open[1] and open < close[1] isBullishEngulfing() => close[1] < open[1] and close > open and high > high[1] and low < low[1] isTweezerBottom() => low == ta.valuewhen(low == ta.lowest(low, 10), low, 0) and low == ta.valuewhen(low == ta.lowest(low, 20), low, 0) isBullishAbandonedBaby() => close[2] < open[2] and close[1] > open[1] and low[1] > ta.valuewhen(high == ta.highest(high, 2), high, 0) and open > close and close > ta.valuewhen(high == ta.highest(high, 2), high, 0) isMorningStar() => close[2] < open[2] and close[1] < open[1] and close > open[1] and open < close[2] and open > close[1] isMorningDojiStar() => close[2] < open[2] and close[1] < open[1] and isDoji() and close > open[1] and open < close[2] and open > close[1] isDragonflyDoji() => isDoji() and (high - close) / (0.001 + high - low) < 0.1 and (open - low) / (0.001 + high - low) > 0.6 isThreeWhiteSoldiers() => close[2] < open[2] and close[1] < open[1] and close > open and open < close[2] and open < close[1] and close > open[1] isRisingThreeMethods() => close[4] < open[4] and close[1] < open[1] and close > open and open < close[4] and open < close[1] and close > open[1] isMarubozuBlack() => close == low and open == high and open > close isGravestoneDoji() => isDoji() and (close - low) / (0.001 + high - low) < 0.1 and (high - open) / (0.001 + high - low) > 0.6 isHangingMan() => (high - low) >= 4 * abs(open - close) and (open - close) / (0.001 + high - low) > 0.6 and (high - open) / (0.001 + high - low) > 0.6 isLongUpperShadow() => (high - open) > 2 * abs(open - close) and (high - close) / (0.001 + high - low) > 0.6 isDownsideTasukiGap() => close[1] > open[1] and open < close and open < close[1] and close > open[1] isFallingWindow() => low[1] > high and close < open isDarkCloudCover() => close[1] > open[1] and close < open and close < ((open + high) / 2) and close > open[1] and open > close[1] isBearishEngulfing() => close[1] > open[1] and close < open and high > high[1] and low < low[1] isTweezerTop() => high == ta.valuewhen(high == ta.highest(high, 10), high, 0) and high == ta.valuewhen(high == ta.highest(high, 20), high, 0) isAbandonedBaby() => close[2] > open[2] and close[1] < open[1] and high[1] < ta.valuewhen(low == ta.lowest(low, 2), low, 0) and open < close and close < ta.valuewhen(low == ta.lowest(low, 2), low, 0) isEveningDojiStar() => close[2] > open[2] and close[1] > open[1] and isDoji() and close < open[1] and open > close[2] and open < close[1] isEveningStar() => close[2] > open[2] and close[1] > open[1] and close < open[1] and open > close[2] and open < close[1] isThreeBlackCrows() => close[2] > open[2] and close[1] > open[1] and close < open and open > close[2] and open > close[1] and close < open[1] isFallingThreeMethods() => close[4] > open[4] and close[1] > open isShootingStar() => (high - low) >= 3 * abs(open - close) and (high - close) / (0.001 + high - low) > 0.6 and (high - open) / (0.001 + high - low) > 0.6 doji = isDoji() marubozuWhite = isMarubozuWhite() hammer = isHammer() invertedHammer = isInvertedHammer() longLowerShadow = isLongLowerShadow() upsideTasukiGap = isUpsideTasukiGap() risingWindow = isRisingWindow() piercing = isPiercing() bullishEngulfing = isBullishEngulfing() tweezerBottom = isTweezerBottom() bullishAbandonedBaby = isBullishAbandonedBaby() morningStar = isMorningStar() morningDojiStar = isMorningDojiStar() dragonflyDoji = isDragonflyDoji() threeWhiteSoldiers = isThreeWhiteSoldiers() risingThreeMethods = isRisingThreeMethods() marubozuBlack = isMarubozuBlack() gravestoneDoji = isGravestoneDoji() hangingMan = isHangingMan() longUpperShadow = isLongUpperShadow() downsideTasukiGap = isDownsideTasukiGap() fallingWindow = isFallingWindow() darkCloudCover = isDarkCloudCover() bearishEngulfing = isBearishEngulfing() tweezerTop = isTweezerTop() abandonedBaby = isAbandonedBaby() eveningDojiStar = isEveningDojiStar() eveningStar = isEveningStar() threeBlackCrows = isThreeBlackCrows() fallingThreeMethods = isFallingThreeMethods() shootingStar = isShootingStar() isBullishPattern() => (isMarubozuWhite() or isHammer() or isInvertedHammer() or isDoji() or isMorningStar() or isBullishEngulfing() or isThreeWhiteSoldiers() or isMarubozuBlack() or isHangingMan() or isDownsideTasukiGap() or isDarkCloudCover()) isBearishPattern() => (isMarubozuBlack() or isInvertedHammer() or isLongUpperShadow() or isTweezerTop() or isGravestoneDoji() or isEveningStar() or isBearishEngulfing() or isThreeBlackCrows() or isShootingStar()) isBullishCandle = isBullishPattern() isBearishCandle = isBearishPattern() // Calculate Pivot Points pivotPoint(high, low, close) => (high + low + close) / 3 r1 = pivotPoint(high[1], low[1], close[1]) * 2 - low[1] s1 = pivotPoint(high[1], low[1], close[1]) * 2 - high[1] r2 = pivotPoint(high[1], low[1], close[1]) + (high[1] - low[1]) s2 = pivotPoint(high[1], low[1], close[1]) - (high[1] - low[1]) r3 = high[1] + 2 * (pivotPoint(high[1], low[1], close[1]) - low[1]) s3 = low[1] - 2 * (high[1] - pivotPoint(high[1], low[1], close[1])) // Trend Identification is_uptrend = close > moving_average is_downtrend = close < moving_average // Entry and Exit Conditions with Trend Identification enterLong = is_uptrend and isBullishCandle and close > r1 exitLong = is_uptrend and (bearishEngulfing or doji or close < s1) enterShort = is_downtrend and isBearishCandle and close < s1 exitShort = is_downtrend and (bullishEngulfing or doji or close > r1) // Strategy Execution if enterLong and strategy.position_size == 0 and strategy.position_size[1] == 0 and close > r1 strategy.entry("Buy", strategy.long, qty=1) if exitLong and strategy.position_size > 0 strategy.close("Buy") if enterShort and strategy.position_size == 0 and close < s1 strategy.entry("Sell", strategy.short, qty=1) if exitShort and strategy.position_size < 0 strategy.close("Sell") // Stop-Loss and Trailing Stop-Loss stop_loss_pct = input(2.0, title="Stop Loss Percentage") trailing_stop_loss_pct = input(1.0, title="Trailing Stop Loss Percentage") trailing_stop_loss_active = input(true, title="Trailing Stop Loss Active") // Stop-Loss stop_loss_level = strategy.position_avg_price * (1 - stop_loss_pct / 100) strategy.exit("Stop Loss", "Buy", loss=stop_loss_level) // Trailing Stop-Loss // Plotting Moving Average plot(moving_average, color=color.blue, title="Moving Average", linewidth=2) // Plotting Candlestick Patterns plotshape(isBullishCandle, title="Bullish Candle", location=location.belowbar, color=color.green, style=shape.labelup) plotshape(isBearishCandle, title="Bearish Candle", location=location.abovebar, color=color.red, style=shape.labeldown) // Plotting Support and Resistance Levels //hline(r1, "Resistance Level 1", color=color.red, linestyle=hline.style_dotted) //hline(s1, "Support Level 1", color=color.green, linestyle=hline.style_dotted)