-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_strategy.pine
More file actions
341 lines (273 loc) · 15.9 KB
/
test_strategy.pine
File metadata and controls
341 lines (273 loc) · 15.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
//@version=5
strategy("Advanced Candlestick Pattern Strategy", overlay=true)
// ============================================
// INPUT PARAMETERS
// ============================================
// Pattern Detection Settings
patternStrength = input.int(3, "Pattern Strength", minval=1, maxval=5, group="Pattern Detection")
bodyRatio = input.float(0.65, "Body/Range Ratio", minval=0.1, maxval=0.9, step=0.05, group="Pattern Detection")
shadowRatio = input.float(2.2, "Shadow/Body Ratio", minval=1.0, maxval=5.0, step=0.1, group="Pattern Detection")
patternLookback = input.int(3, "Pattern Lookback", minval=1, maxval=10, group="Pattern Detection")
minPatternSize = input.float(0.5, "Min Pattern Size (ATR)", minval=0.3, maxval=2.0, step=0.1, group="Pattern Detection")
// Enable/Disable Patterns
enableHammer = input.bool(true, "Hammer & Hanging Man", group="Reversal Patterns")
enableDoji = input.bool(true, "Doji Family", group="Reversal Patterns")
enableEngulfing = input.bool(true, "Engulfing Patterns", group="Reversal Patterns")
enableStar = input.bool(true, "Morning/Evening Star", group="Reversal Patterns")
enableHarami = input.bool(true, "Harami Patterns", group="Reversal Patterns")
enablePiercing = input.bool(true, "Piercing Line/Dark Cloud", group="Reversal Patterns")
enableShootingStar = input.bool(true, "Shooting Star", group="Reversal Patterns")
enableInvertedHammer = input.bool(true, "Inverted Hammer", group="Reversal Patterns")
// Confirmation Settings
useVolumeConfirmation = input.bool(true, "Volume Confirmation", group="Confirmations")
volumeMultiplier = input.float(1.15, "Volume Multiple", minval=1.0, maxval=3.0, step=0.1, group="Confirmations")
useTrendConfirmation = input.bool(true, "Trend Confirmation", group="Confirmations")
trendPeriod = input.int(20, "Trend EMA Period", minval=5, maxval=50, group="Confirmations")
useRSIConfirmation = input.bool(true, "RSI Confirmation", group="Confirmations")
rsiPeriod = input.int(14, "RSI Period", minval=5, maxval=30, group="Confirmations")
rsiOverbought = input.int(70, "RSI Overbought", minval=60, maxval=90, group="Confirmations")
rsiOversold = input.int(30, "RSI Oversold", minval=10, maxval=40, group="Confirmations")
useMAConfirmation = input.bool(false, "Moving Average Filter", group="Confirmations")
maFastPeriod = input.int(9, "Fast MA Period", minval=5, maxval=20, group="Confirmations")
maSlowPeriod = input.int(21, "Slow MA Period", minval=10, maxval=50, group="Confirmations")
useVolatilityFilter = input.bool(false, "Volatility Filter", group="Confirmations")
volatilityPeriod = input.int(20, "Volatility Period", minval=10, maxval=50, group="Confirmations")
minVolatility = input.float(0.8, "Min Volatility Threshold", minval=0.5, maxval=3.0, step=0.1, group="Confirmations")
// Risk Management
stopLossType = input.string("ATR", "Stop Loss Type", options=["Percentage", "ATR", "Pattern Based"], group="Risk Management")
stopLossPercent = input.float(1.5, "Stop Loss %", minval=0.5, maxval=10, step=0.1, group="Risk Management")
atrPeriod = input.int(14, "ATR Period", minval=5, maxval=30, group="Risk Management")
atrMultiplier = input.float(1.6, "ATR Multiplier", minval=1.0, maxval=5.0, step=0.1, group="Risk Management")
takeProfitRatio = input.float(3.2, "Risk/Reward Ratio", minval=1.0, maxval=10.0, step=0.5, group="Risk Management")
useTrailingStop = input.bool(true, "Trailing Stop", group="Risk Management")
trailingStopPercent = input.float(1.0, "Trailing Stop %", minval=0.5, maxval=5.0, step=0.1, group="Risk Management")
useBreakeven = input.bool(true, "Move to Breakeven", group="Risk Management")
breakevenRatio = input.float(1.0, "Breakeven at R:R", minval=0.5, maxval=2.0, step=0.1, group="Risk Management")
useDynamicSizing = input.bool(true, "Dynamic Position Sizing", group="Risk Management")
maxRiskPerTrade = input.float(1.0, "Max Risk Per Trade %", minval=0.1, maxval=5.0, step=0.1, group="Risk Management")
// ============================================
// TECHNICAL INDICATORS
// ============================================
// ATR for volatility-based stops
atrValue = ta.atr(atrPeriod)
// Trend confirmation
ema = ta.ema(close, trendPeriod)
uptrend = close > ema
downtrend = close < ema
// Moving Average Filter
maFast = ta.ema(close, maFastPeriod)
maSlow = ta.ema(close, maSlowPeriod)
bullishTrendMA = maFast > maSlow and close > maFast
bearishTrendMA = maFast < maSlow and close < maFast
// RSI for momentum confirmation
rsi = ta.rsi(close, rsiPeriod)
rsiOverboughtCondition = rsi > rsiOverbought
rsiOversoldCondition = rsi < rsiOversold
rsiNeutral = rsi > 40 and rsi < 60
// Volume confirmation
avgVolume = ta.sma(volume, 20)
highVolume = volume > avgVolume * volumeMultiplier
// Volatility Filter
volatility = ta.stdev(ta.change(close), volatilityPeriod) / close * 100
highVolatility = volatility > minVolatility
// ============================================
// CANDLESTICK PATTERN FUNCTIONS
// ============================================
// Basic candle properties
bodySize = math.abs(close - open)
totalRange = high - low
upperShadow = high - math.max(close, open)
lowerShadow = math.min(close, open) - low
bodyRatioActual = totalRange > 0 ? bodySize / totalRange : 0
upperShadowRatio = bodySize > 0 ? upperShadow / bodySize : 0
lowerShadowRatio = bodySize > 0 ? lowerShadow / bodySize : 0
// Color determination
bullishCandle = close > open
bearishCandle = close < open
// ============================================
// PATTERN DETECTION FUNCTIONS
// ============================================
// Doji Pattern
isDoji() =>
bodyRatioActual < 0.1 and totalRange > atrValue * 0.5
// Hammer Pattern (bullish reversal at bottom)
isHammer() => lowerShadow >= bodySize * shadowRatio and upperShadow <= bodySize * 0.5 and bodyRatioActual >= bodyRatio * 0.5 and bodyRatioActual <= 0.8
// Shooting Star Pattern (bearish reversal at top)
isShootingStar() => upperShadow >= bodySize * shadowRatio and lowerShadow <= bodySize * 0.5 and bodyRatioActual >= bodyRatio * 0.5 and bodyRatioActual <= 0.8
// Inverted Hammer (bullish reversal at bottom)
isInvertedHammer() => upperShadow >= bodySize * shadowRatio and lowerShadow <= bodySize * 0.5 and bodyRatioActual >= bodyRatio * 0.5
// Bullish Engulfing
isBullishEngulfing() => bearishCandle[1] and bullishCandle and open <= close[1] and close > open[1] and bodySize > bodySize[1] * 1.2
// Bearish Engulfing
isBearishEngulfing() => bullishCandle[1] and bearishCandle and open >= close[1] and close < open[1] and bodySize > bodySize[1] * 1.2
// Morning Star (3-candle bullish reversal)
isMorningStar() => bearishCandle[2] and bodySize[2] > atrValue and bodyRatioActual[1] < 0.3 and bullishCandle and close > (open[2] + close[2]) / 2
// Evening Star (3-candle bearish reversal)
isEveningStar() => bullishCandle[2] and bodySize[2] > atrValue and bodyRatioActual[1] < 0.3 and bearishCandle and close < (open[2] + close[2]) / 2
// Bullish Harami
isBullishHarami() => bearishCandle[1] and bullishCandle and open > close[1] and close < open[1] and bodySize < bodySize[1] * 0.7
// Bearish Harami
isBearishHarami() => bullishCandle[1] and bearishCandle and open < close[1] and close > open[1] and bodySize < bodySize[1] * 0.7
// Piercing Line (bullish reversal)
isPiercingLine() => bearishCandle[1] and bullishCandle and open < low[1] and close > (open[1] + close[1]) / 2 and close < open[1]
// Dark Cloud Cover (bearish reversal)
isDarkCloud() => bullishCandle[1] and bearishCandle and open > high[1] and close < (open[1] + close[1]) / 2 and close > open[1]
// ============================================
// PATTERN DETECTION LOGIC
// ============================================
// Bullish patterns
bullishDoji = enableDoji and isDoji() and downtrend
bullishHammer = enableHammer and isHammer() and downtrend
bullishInvertedHammer = enableInvertedHammer and isInvertedHammer() and downtrend
bullishEngulfing = enableEngulfing and isBullishEngulfing()
bullishMorningStar = enableStar and isMorningStar()
bullishHarami = enableHarami and isBullishHarami()
bullishPiercing = enablePiercing and isPiercingLine()
// Bearish patterns
bearishDoji = enableDoji and isDoji() and uptrend
bearishShootingStar = enableShootingStar and isShootingStar() and uptrend
bearishHangingMan = enableHammer and isHammer() and uptrend
bearishEngulfing = enableEngulfing and isBearishEngulfing()
bearishEveningStar = enableStar and isEveningStar()
bearishHarami = enableHarami and isBearishHarami()
bearishDarkCloud = enablePiercing and isDarkCloud()
// Combined pattern signals
bullishPatternDetected = bullishDoji or bullishHammer or bullishInvertedHammer or bullishEngulfing or bullishMorningStar or bullishHarami or bullishPiercing
bearishPatternDetected = bearishDoji or bearishShootingStar or bearishHangingMan or bearishEngulfing or bearishEveningStar or bearishHarami or bearishDarkCloud
// ============================================
// CONFIRMATION CONDITIONS
// ============================================
// Volume confirmation
volumeConfirmed = useVolumeConfirmation ? highVolume : true
// Trend confirmation - more relaxed
trendConfirmedBullish = useTrendConfirmation ? (close > ema * 0.99 or not uptrend) : true
trendConfirmedBearish = useTrendConfirmation ? (close < ema * 1.01 or not downtrend) : true
// MA confirmation
maConfirmedBullish = useMAConfirmation ? bullishTrendMA : true
maConfirmedBearish = useMAConfirmation ? bearishTrendMA : true
// RSI confirmation - more relaxed
rsiConfirmedBullish = useRSIConfirmation ? (rsi < 55 and not rsiOverboughtCondition) : true
rsiConfirmedBearish = useRSIConfirmation ? (rsi > 45 and not rsiOversoldCondition) : true
// Volatility confirmation
volatilityConfirmed = useVolatilityFilter ? highVolatility : true
// ============================================
// ENTRY CONDITIONS
// ============================================
// Long entry condition - balanced
longCondition = bullishPatternDetected and volumeConfirmed and trendConfirmedBullish and rsiConfirmedBullish
// Short entry condition - balanced
shortCondition = bearishPatternDetected and volumeConfirmed and trendConfirmedBearish and rsiConfirmedBearish
// ============================================
// STOP LOSS CALCULATION
// ============================================
calculateStopLoss(isLong) =>
if stopLossType == "Percentage"
if isLong
close * (1 - stopLossPercent / 100)
else
close * (1 + stopLossPercent / 100)
else if stopLossType == "ATR"
if isLong
close - atrValue * atrMultiplier
else
close + atrValue * atrMultiplier
else // Pattern Based
if isLong
math.min(low, low[1]) - atrValue * 0.5
else
math.max(high, high[1]) + atrValue * 0.5
// ============================================
// POSITION MANAGEMENT
// ============================================
var float longStopLoss = na
var float shortStopLoss = na
var float longTakeProfit = na
var float shortTakeProfit = na
calculatePositionSize(stopDistance) =>
if useDynamicSizing
riskAmount = strategy.equity * maxRiskPerTrade / 100
math.min(riskAmount / stopDistance, strategy.equity * 0.1)
else
strategy.equity * 0.08
// Execute long trades with dynamic sizing
if longCondition and strategy.position_size == 0
stopLoss = calculateStopLoss(true)
stopDistance = close - stopLoss
takeProfit = close + stopDistance * takeProfitRatio
posSize = calculatePositionSize(stopDistance)
strategy.entry("Long", strategy.long, qty=posSize)
longStopLoss := stopLoss
longTakeProfit := takeProfit
// Execute short trades with dynamic sizing
if shortCondition and strategy.position_size == 0
stopLoss = calculateStopLoss(false)
stopDistance = stopLoss - close
takeProfit = close - stopDistance * takeProfitRatio
posSize = calculatePositionSize(stopDistance)
strategy.entry("Short", strategy.short, qty=posSize)
shortStopLoss := stopLoss
shortTakeProfit := takeProfit
// Breakeven logic
if useBreakeven and strategy.position_size > 0
breakevenPrice = strategy.position_avg_price + (longTakeProfit - strategy.position_avg_price) * breakevenRatio / takeProfitRatio
if close >= breakevenPrice and longStopLoss < strategy.position_avg_price
longStopLoss := strategy.position_avg_price + atrValue * 0.1
if useBreakeven and strategy.position_size < 0
breakevenPrice = strategy.position_avg_price - (strategy.position_avg_price - shortTakeProfit) * breakevenRatio / takeProfitRatio
if close <= breakevenPrice and shortStopLoss > strategy.position_avg_price
shortStopLoss := strategy.position_avg_price - atrValue * 0.1
// Partial profit taking
if strategy.position_size > 0
// Take 30% profit at 1.5R
if close >= strategy.position_avg_price + (longTakeProfit - strategy.position_avg_price) * 0.6
strategy.close("Long", qty_percent=30, comment="Partial TP 1")
// Take another 30% at 2R
if close >= strategy.position_avg_price + (longTakeProfit - strategy.position_avg_price) * 0.8
strategy.close("Long", qty_percent=30, comment="Partial TP 2")
strategy.exit("Long Exit", "Long", stop=longStopLoss, limit=longTakeProfit)
// Enhanced trailing stop
if useTrailingStop and close > strategy.position_avg_price * (1 + trailingStopPercent / 100)
trailDistance = atrValue * 1.5
newStop = close - trailDistance
if newStop > longStopLoss
longStopLoss := newStop
if strategy.position_size < 0
// Take 30% profit at 1.5R
if close <= strategy.position_avg_price - (strategy.position_avg_price - shortTakeProfit) * 0.6
strategy.close("Short", qty_percent=30, comment="Partial TP 1")
// Take another 30% at 2R
if close <= strategy.position_avg_price - (strategy.position_avg_price - shortTakeProfit) * 0.8
strategy.close("Short", qty_percent=30, comment="Partial TP 2")
strategy.exit("Short Exit", "Short", stop=shortStopLoss, limit=shortTakeProfit)
// Enhanced trailing stop
if useTrailingStop and close < strategy.position_avg_price * (1 - trailingStopPercent / 100)
trailDistance = atrValue * 1.5
newStop = close + trailDistance
if newStop < shortStopLoss
shortStopLoss := newStop
// ============================================
// VISUALIZATION
// ============================================
// Plot trend EMA
plot(ema, "Trend EMA", color=color.orange, linewidth=1)
plot(maFast, "Fast MA", color=color.blue, linewidth=1)
plot(maSlow, "Slow MA", color=color.red, linewidth=1)
// Plot pattern signals
// Plot pattern signals
plotshape(bullishPatternDetected and volumeConfirmed, title="Bullish Pattern", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(bearishPatternDetected and volumeConfirmed, title="Bearish Pattern", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
// Plot entry signals
plotshape(longCondition, title="Long Entry", location=location.belowbar, color=color.lime, style=shape.arrowup, size=size.normal)
plotshape(shortCondition, title="Short Entry", location=location.abovebar, color=color.fuchsia, style=shape.arrowdown, size=size.normal)
// Plot stop levels
plot(strategy.position_size > 0 ? longStopLoss : na, "Long Stop", color=color.red, style=plot.style_linebr)
plot(strategy.position_size < 0 ? shortStopLoss : na, "Short Stop", color=color.red, style=plot.style_linebr)
plot(strategy.position_size > 0 ? longTakeProfit : na, "Long Target", color=color.green, style=plot.style_linebr)
plot(strategy.position_size < 0 ? shortTakeProfit : na, "Short Target", color=color.green, style=plot.style_linebr)
// Background color for trend
bgcolor(uptrend ? color.new(color.green, 95) : color.new(color.red, 95), title="Trend Background")
// ============================================
// ALERTS
// ============================================
alertcondition(longCondition, title="Bullish Pattern Alert", message="Bullish candlestick pattern detected - Consider LONG")
alertcondition(shortCondition, title="Bearish Pattern Alert", message="Bearish candlestick pattern detected - Consider SHORT")