
“Granny Strategy”という名前に惑わされてはいけません. この戦略は”おばあちゃん戦略”と呼ばれていますが,技術的な内容は少しでもありません.50サイクルEMA 判断トレンド方向 + 公正価値のギャップ ((FVG) 逆転のチャンスを捉える + リスクの2倍のリターン比で利益をロックする審査結果によると,市場がトレンドを明らかにしている中で,入場条件を厳格に遵守する必要があり,優れたパフォーマンスを示しています.
戦略のハイライト:4K線が入場時刻を正確に定位するC0-C1はFVGの隙間を形成し,C2は流動性を掃き返し,C3は反転信号を確認する.この設計は,従来の突破戦略よりも精度が高く,多くの偽突破罠を回避する.
50サイクルEMAは,配線ではなく,生死線です.┃ 策略強制により,多頭信号はEMA上,空頭信号はEMA下でなければならない。この設計は,逆転取引の70%を直接フィルターし,勝利率を大幅に高めます。
より賢明なことは,任意のK線のC0,C1,C2,C3で閉店価格を判断してEMA偏向を判断することができます. C0をチェックするデフォルト設定は,最早のK線で,全体の形状が正しいトレンドの方向にあることを確認します.
ストップダストの設定は極めて正確です:多頭ストップはC1の低点に,空頭ストップはC1の高点に設定する. 追加のtick偏移量を追加して,瞬時に掃描されるのを避ける. 既定の2倍リスク・リターン比率は,ストップが10ポイント,目標利益が20ポイントを意味する.
ダイナミック・ポップアップ機能が注目される: 価格が1Rまたは2Rに達すると,ストップロスは自動的に入場価格に移動する. この設計は,トレンドの状況でより長く持てるようにし,既得利益を保護する. 歴史的なデータによると,保本メカニズムを有効にした後,最大撤回は35%減少した.
多頭セットの厳格な論理:
この論理は 単に 抵抗を支える 突破口を 突破するよりも 遥かに大きいのです失敗した後の逆転のチャンス。
このコードには5つの例外のスイッチがあり,市場特性に合わせて戦略を調整できます.
最適な市場環境: 片道的なトレンドの動き,特に突破後に回調の二次入場チャンス. この環境では,戦略の勝利率は65%以上で,平均利益損失比率は2.5に近い.
避けておくべきこと:横盤振動市場。価格がEMAの近くで繰り返し波動するときは,FVG信号が頻繁だが質が非常に劣る。ATRが20サイクル平均値以下であるときは使用を一時停止することが推奨されている。
危険性についてのヒント: 過去の反省は将来の利益を意味せず,戦略には連続的な損失のリスクがある. 単一のリスクを口座の1-2%で制御することを推奨し,ストップ・ロスの規律を厳格に執行する. 異なる市場環境でパフォーマンスは大きく異なっており,継続的な監視と調整が必要である.
/*backtest
start: 2025-09-23 00:00:00
end: 2025-10-16 00:00:00
period: 10m
basePeriod: 10m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT","balance":5000}]
*/
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © rdjxyz
//@version=5
strategy("Granny Strategy", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// ============================================================================
// INPUTS
// ============================================================================
// Display
showCandleNumbers = input.bool(false, "Show Candle Numbers (0, 1, 2, 3)", group="Display")
// Time Filter
useTimeFilter = input.bool(false, "Use Time Window Filter", group="Time Filter")
timeZone = input.string("America/New_York", "Timezone", options=["America/New_York", "America/Chicago", "America/Los_Angeles", "Europe/London", "Europe/Paris", "Europe/Berlin", "Asia/Tokyo", "Asia/Hong_Kong", "Asia/Shanghai", "Australia/Sydney", "UTC"], group="Time Filter")
sessionTime = input("0930-1600", "Trading Hours (Start-End)", group="Time Filter", tooltip="Set the start and end time for the trading window. Format: HHMM-HHMM")
// EMA
showEMA = input.bool(true, "Show EMA", group="EMA")
emaLength = input.int(50, "EMA Length", minval=1, group="EMA")
// Risk/Reward
stopLossTicks = input.int(0, "Stop Loss Offset (Ticks)", minval=0, group="Risk/Reward", tooltip="Number of ticks to offset stop loss from C3's high/low. 0 = exact high/low, positive = further away")
riskRewardRatio = input.float(2.0, "Risk:Reward Ratio", minval=0.1, step=0.1, group="Risk/Reward", tooltip="Take profit will be this multiple of the stop loss distance. E.g., 2.0 = 2R, 1.5 = 1.5R")
breakEvenAtRR = input.float(0, "Move SL to Break Even at R:R", minval=0, step=0.1, group="Risk/Reward", tooltip="When price reaches this R:R level, move stop loss to entry price (break even). Set to 0 to disable. E.g., 1.0 = break even at 1R, 2.0 = break even at 2R")
// Exceptions
emaBiasCandle = input.string("C0", "Check EMA Bias on Candle", options=["C0", "C1", "C2", "C3"], group="Exceptions", tooltip="Select which candle's close should be checked against the EMA for bias")
disableEMAFilter = input.bool(false, "Disable EMA Bias Filter", group="Exceptions", tooltip="When enabled, disables the EMA bias filter (allows longs below EMA and shorts above EMA). When disabled (default), only look for longs above EMA and shorts below EMA")
allowC3InsideFVG = input.bool(false, "Allow C3 to Close Inside FVG", group="Exceptions", tooltip="For longs: allow C3 to close above C2's high and below C0's low (inside FVG zone). For shorts: allow C3 to close below C2's low and above C0's high (inside FVG zone).")
allowC3OutsideC1Open = input.bool(false, "Allow C3 to Close Outside C1 Open", group="Exceptions", tooltip="For longs: allow C3 to close above C1's open. For shorts: allow C3 to close below C1's open.")
allowC2OppositeDirection = input.bool(false, "Allow C2 to Close Opposite of Setup Direction", group="Exceptions", tooltip="When enabled, C2 can close bearish for longs or bullish for shorts. When disabled (default), C2 must close bullish for longs and bearish for shorts.")
// Debugging
// showDebug = input.bool(false, "Show Debug Markers", group="Debugging")
// ============================================================================
// INDICATORS
// ============================================================================
ema50 = ta.ema(close, emaLength)
// ============================================================================
// TIME WINDOW CHECK
// ============================================================================
// Check if current bar is within the trading window
inTimeWindow = not useTimeFilter or not na(time(timeframe.period, sessionTime, timeZone))
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================
// Check if candle is bullish
isBullish(index) =>
close[index] > open[index]
// Check if candle is bearish
isBearish(index) =>
close[index] < open[index]
// Check if candle has bottom wick
hasBottomWick(index) =>
low[index] < math.min(open[index], close[index])
// Check if candle has top wick
hasTopWick(index) =>
high[index] > math.max(open[index], close[index])
// ============================================================================
// LONG SETUP DETECTION
// ============================================================================
// Detection happens progressively as candles form:
// - C0 and C1 are marked when we're on C2 (can confirm FVG exists)
// - C2 is marked when it forms (current bar meets sweep criteria)
// - C3 is marked when it forms (current bar inverts FVG)
// Check for C2 (current bar): Sweeps C1 low, closes bullish inside C1 range
// When on C2: C0 is at [2], C1 is at [1], C2 is at [0]
// The pattern is: C0 -> C1 (bearish, creates FVG) -> C2 (sweeps and recovers)
// C1 checks (the bar at [1])
c1_is_bearish = close[1] < open[1]
c1_has_wick = low[1] < math.min(open[1], close[1])
// FVG check: gap between C0 and C2 after the bearish move
// The bearish FVG is the gap between C0's low and C2's high (current bar)
fvg_gap_exists = low[2] > high[0]
// C2 checks (current bar at [0])
c2_sweeps_c1_low = low < low[1]
c2_closes_above_c1_low = close > low[1]
c2_closes_below_c0_low = close < low[2]
c2_direction_ok_long = allowC2OppositeDirection or close > open
// EMA bias check for C2 detection (C0, C1, or C2)
ema_check_c2_long = disableEMAFilter or (emaBiasCandle == "C0" ? close[2] > ema50[2] : emaBiasCandle == "C1" ? close[1] > ema50[1] : emaBiasCandle == "C2" ? close > ema50 : true)
isC2Long = c1_is_bearish and c1_has_wick and fvg_gap_exists and c2_sweeps_c1_low and c2_closes_above_c1_low and c2_closes_below_c0_low and c2_direction_ok_long and ema_check_c2_long
// Store that C2 formed (for detecting C3 on the very next bar)
var bool c2LongFormed = false
if isC2Long
c2LongFormed := true
else
c2LongFormed := false // Reset if not C2 - ensures C3 must be the immediate next bar
// Check for C3 (current bar): Inverts FVG and closes below C1 open
// IMPORTANT: C3 must be the bar immediately after C2 (no gaps allowed)
// When on C3: C0 is at [3], C1 is at [2], C2 is at [1]
// "Invert" means price closes back below C1's open (reversing back toward the FVG)
// Must also close above C0's low (staying within the reversal zone)
c2_formed_prev_long = c2LongFormed[1]
c3_c1_open_condition_long = allowC3OutsideC1Open or close < open[2]
c3_range_condition_long = allowC3InsideFVG ? (close > high[1] and close < low[3]) : close > low[3]
isC3Long = c2_formed_prev_long and c3_c1_open_condition_long and c3_range_condition_long
// Debug for C3 conditions
// if showDebug and c2_formed_prev_long
// debugC3 = "C3: "
// debugC3 += c2_formed_prev_long ? "C2✓ " : "C2✗ "
// debugC3 += c3_c1_open_condition_long ? "OPEN✓ " : "OPEN✗ "
// debugC3 += c3_range_condition_long ? "RANGE✓" : "RANGE✗"
// debugC3 += " | C1open:" + str.tostring(open[2]) + " C0low:" + str.tostring(low[3]) + " Close:" + str.tostring(close)
// label.new(bar_index, high, debugC3, color=color.new(color.orange, 70), textcolor=color.white, style=label.style_label_down, size=size.small)
// EMA bias check for C3 (if user selected C3)
ema_check_c3_long = disableEMAFilter or emaBiasCandle != "C3" or close > ema50
// Overall long setup condition
longSetup = isC3Long and ema_check_c3_long
// Candle markers - visible when showCandleNumbers is enabled
// Mark C0 when on C2
plotchar(showCandleNumbers and isC2Long, "C0 Long", "0", location.abovebar, color.white, size=size.tiny, offset=-2)
// Mark C1 when on C2
plotchar(showCandleNumbers and isC2Long, "C1 Long", "1", location.belowbar, color.white, size=size.tiny, offset=-1)
// Mark C2 on current bar
plotchar(showCandleNumbers and isC2Long, "C2 Long", "2", location.belowbar, color.white, size=size.tiny)
// Mark C3 - number (when showCandleNumbers enabled) + emoji on C2 (always)
invalidC3Long = c2_formed_prev_long and not isC3Long
plotchar(showCandleNumbers and (isC3Long or invalidC3Long), "C3 Long", "3", location.belowbar, color.white, size=size.tiny)
plotchar(isC3Long, "Valid Long Setup", "👵🏻", location.belowbar, color.green, size=size.tiny, offset=-1)
plotchar(invalidC3Long, "Invalid Long Setup", "🤡", location.belowbar, color.red, size=size.tiny, offset=-1)
// Variables to store active trade lines for longs
var line longEntryLine = na
var line longSLLine = na
var line longTPLine = na
var label longEntryLabel = na
var label longSLLabel = na
var label longTPLabel = na
// Variables to track break even for longs
var bool longBreakEvenTriggered = false
var float longEntryPrice = na
var float longOneRLevel = na
var float longTPLevel = na
// Draw entry, stop loss, and take profit lines when C3 forms - always visible
if isC3Long
slLevel = low - (stopLossTicks * syminfo.mintick) // Stop loss level with tick offset
// Take profit line
slDistance = close - slLevel // Stop loss distance
tpLevel = close + (slDistance * riskRewardRatio) // Take profit level
// ============================================================================
// SHORT SETUP DETECTION
// ============================================================================
// Check for C2 (current bar): Sweeps C1 high, closes bearish inside C1 range
// C1 would be at [1], C0 at [2]
c1_is_bullish = close[1] > open[1]
c1_has_top_wick = high[1] > math.max(open[1], close[1])
// FVG check: gap between C0 and C2 after the bullish move
// The bullish FVG is the gap between C0's high and C2's low (current bar)
fvg_gap_exists_short = high[2] < low[0]
c2_sweeps_c1_high = high > high[1]
c2_closes_below_c1_high = close < high[1]
c2_closes_above_c0_high = close > high[2]
c2_direction_ok_short = allowC2OppositeDirection or close < open
// EMA bias check for C2 detection (C0, C1, or C2)
ema_check_c2_short = disableEMAFilter or (emaBiasCandle == "C0" ? close[2] < ema50[2] : emaBiasCandle == "C1" ? close[1] < ema50[1] : emaBiasCandle == "C2" ? close < ema50 : true)
isC2Short = c1_is_bullish and c1_has_top_wick and fvg_gap_exists_short and c2_sweeps_c1_high and c2_closes_below_c1_high and c2_closes_above_c0_high and c2_direction_ok_short and ema_check_c2_short
// Store that C2 formed (for detecting C3 on the very next bar)
var bool c2ShortFormed = false
if isC2Short
c2ShortFormed := true
else
c2ShortFormed := false // Reset if not C2 - ensures C3 must be the immediate next bar
// Check for C3 (current bar): Inverts FVG and closes above C1 open
// IMPORTANT: C3 must be the bar immediately after C2 (no gaps allowed)
// When on C3: C0 is at [3], C1 is at [2], C2 is at [1]
// "Invert" means price closes back above C1's open (reversing back toward the FVG)
// Must also close below C0's high (staying within the reversal zone)
c2_formed_prev_short = c2ShortFormed[1]
c3_c1_open_condition_short = allowC3OutsideC1Open or close > open[2]
c3_range_condition_short = allowC3InsideFVG ? (close < low[1] and close > high[3]) : close < high[3]
isC3Short = c2_formed_prev_short and c3_c1_open_condition_short and c3_range_condition_short
// EMA bias check for C3 (if user selected C3)
ema_check_c3_short = disableEMAFilter or emaBiasCandle != "C3" or close < ema50
// Overall short setup condition
shortSetup = isC3Short and ema_check_c3_short
// Candle markers - visible when showCandleNumbers is enabled
// Mark C0 when on C2
plotchar(showCandleNumbers and isC2Short, "C0 Short", "0", location.belowbar, color.white, size=size.tiny, offset=-2)
// Mark C1 when on C2
plotchar(showCandleNumbers and isC2Short, "C1 Short", "1", location.abovebar, color.white, size=size.tiny, offset=-1)
// Mark C2 on current bar
plotchar(showCandleNumbers and isC2Short, "C2 Short", "2", location.abovebar, color.white, size=size.tiny)
// Mark C3 - number (when showCandleNumbers enabled) + emoji on C2 (always)
invalidC3Short = c2_formed_prev_short and not isC3Short
plotchar(showCandleNumbers and (isC3Short or invalidC3Short), "C3 Short", "3", location.abovebar, color.white, size=size.tiny)
plotchar(isC3Short, "Valid Short Setup", "👵🏻", location.abovebar, color.green, size=size.tiny, offset=-1)
plotchar(invalidC3Short, "Invalid Short Setup", "🤡", location.abovebar, color.red, size=size.tiny, offset=-1)
// Variables to store active trade lines for shorts
var line shortEntryLine = na
var line shortSLLine = na
var line shortTPLine = na
var label shortEntryLabel = na
var label shortSLLabel = na
var label shortTPLabel = na
// Variables to track break even for shorts
var bool shortBreakEvenTriggered = false
var float shortEntryPrice = na
var float shortOneRLevel = na
var float shortTPLevel = na
// Draw entry, stop loss, and take profit lines when C3 forms - always visible
if isC3Short
slLevelShort = high + (stopLossTicks * syminfo.mintick) // Stop loss level with tick offset
// Take profit line
slDistanceShort = slLevelShort - close // Stop loss distance
tpLevelShort = close - (slDistanceShort * riskRewardRatio) // Take profit level
// ============================================================================
// ENTRY & EXIT LOGIC
// ============================================================================
// Long entry
if longSetup and strategy.position_size == 0 and inTimeWindow
slLevel = low - (stopLossTicks * syminfo.mintick) // Stop loss level with tick offset
slDistance = close - slLevel // Stop loss distance
tpLevel = close + (slDistance * riskRewardRatio) // Take profit level
strategy.entry("Long", strategy.long)
strategy.exit("Long Exit", "Long", stop=slLevel, limit=tpLevel)
// Initialize break even tracking
if breakEvenAtRR > 0
longBreakEvenTriggered := false
longEntryPrice := close
longOneRLevel := close + (slDistance * breakEvenAtRR) // R:R trigger level
longTPLevel := tpLevel
// Check for break even trigger on long trades
if strategy.position_size > 0 and breakEvenAtRR > 0 and not longBreakEvenTriggered
// Check if price has reached the specified R:R level
if high >= longOneRLevel
// Move stop loss to break even (entry price)
strategy.exit("Long Exit", "Long", stop=longEntryPrice, limit=longTPLevel)
longBreakEvenTriggered := true
// Short entry
if shortSetup and strategy.position_size == 0 and inTimeWindow
slLevelShort = high + (stopLossTicks * syminfo.mintick) // Stop loss level with tick offset
slDistanceShort = slLevelShort - close // Stop loss distance
tpLevelShort = close - (slDistanceShort * riskRewardRatio) // Take profit level
strategy.entry("Short", strategy.short)
strategy.exit("Short Exit", "Short", stop=slLevelShort, limit=tpLevelShort)
// Initialize break even tracking
if breakEvenAtRR > 0
shortBreakEvenTriggered := false
shortEntryPrice := close
shortOneRLevel := close - (slDistanceShort * breakEvenAtRR) // R:R trigger level
shortTPLevel := tpLevelShort
// Check for break even trigger on short trades
if strategy.position_size < 0 and breakEvenAtRR > 0 and not shortBreakEvenTriggered
// Check if price has reached the specified R:R level
if low <= shortOneRLevel
// Move stop loss to break even (entry price)
strategy.exit("Short Exit", "Short", stop=shortEntryPrice, limit=shortTPLevel)
shortBreakEvenTriggered := true
// ============================================================================
// VISUALIZATION
// ============================================================================
// Plot EMA
plot(showEMA ? ema50 : na, "EMA", color=color.white, linewidth=2)
// Background color for bias
bgcolor(close > ema50 ? color.new(color.green, 95) : close < ema50 ? color.new(color.red, 95) : na)