Repository navigation
Expand file tree
/
Copy pathStrategyTemplate.pine
More file actions
453 lines (340 loc) · 33.6 KB
/
Copy pathStrategyTemplate.pine
File metadata and controls
453 lines (340 loc) · 33.6 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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//@version=5
strategy("Strat Template", shorttitle='VxV:template', overlay=true, format=format.price, precision=2, margin_long=100, margin_short=100)
// Using ATR for Stop Loss calculation (if used)
//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
atrPeriod = input.int(title='ATR Period', defval=3, minval=1, group="ATR Bands Standard Settings", tooltip="This setting is used in the raw ATR value calculation. Lower values will be more reactive to recent price movement, while higher values will better indicate loger-term trend.\n\n" +
"Most often this is set at either 14 or 21.\nDefault: 3")
atrMultiplier = input.float(title='ATR Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Bands Standard Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " +
"This will usually be between 1 and 3.\n\nDefault: 2.5")
tf_atr = input.timeframe(defval='60', title="ATR Time Frame Resolution", group="ATR Bands Standard Settings")
// ATR
atr = request.security(syminfo.tickerid, tf_atr, ta.atr(atrPeriod), barmerge.gaps_off, barmerge.lookahead_on) //* 100 / sourceInput
scaledATR = atr * atrMultiplier
upperATRBand = request.security(syminfo.tickerid, tf_atr, high, barmerge.gaps_off, barmerge.lookahead_on) + scaledATR // should we use current timeframe or a different time frame. Need to experiment here
lowerATRBand = request.security(syminfo.tickerid, tf_atr, low, barmerge.gaps_off, barmerge.lookahead_on) - scaledATR
natr = 100 * ta.atr(atrPeriod) / close
//slValue = float (0)
// OG ATR Band Plotting for debugging
//plot(upperATRBand, title="Upper ATR Band", color=color.rgb(0, 255, 0, 50), linewidth=2)
//plot(lowerATRBand, title="Lower ATR Band", color=color.rgb(255, 0, 0, 50), linewidth=2)
// EMA Filter
//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_emaFilterEnabled = input.bool(defval = false , title = "Enable HMA Filter", tooltip = "Enable if you would like to conditionally have entries incorporate EMA as a filter where source is above/below the EMA line", group ="EMA Filter" )
i_emaLength = input.int(50, title="EMA Length", minval=1, group ="EMA Filter")
i_emaSource = input.source(close,"EMA Source" , group ="EMA Filter")
//emaValue = i_emaFilterEnabled ? ta.ema(i_emaSource, i_emaLength) : na
//emaValue = ta.hma(i_emaSource, i_emaLength)
emaValue = request.security(syminfo.tickerid, tf_atr, ta.hma(i_emaSource, i_emaLength), barmerge.gaps_off, barmerge.lookahead_on)
// Idea here is that you can use a higher value for this
emaValueForTrend = request.security(syminfo.tickerid, tf_atr, ta.hma(i_emaSource, 81), barmerge.gaps_off, barmerge.lookahead_on)
[md,sig,hist] = request.security(syminfo.tickerid, tf_atr, ta.macd(i_emaSource,12,26,9), barmerge.gaps_off, barmerge.lookahead_on)
bool isEMATrendUp = i_emaFilterEnabled ? emaValueForTrend[1] < emaValueForTrend : true
bool isEMATrendDown = i_emaFilterEnabled ? emaValueForTrend[1] > emaValueForTrend : true
bool isEMAFilterEnabledAndCloseAboveMA = i_emaFilterEnabled ? i_emaSource > emaValue : true
bool isEMAFilterEnabledAndCloseBelowMA = i_emaFilterEnabled ? i_emaSource < emaValue : true
//bool isEMAFilterEnabledAndCloseAboveMA = i_emaFilterEnabled ? sig < md : true
//bool isEMAFilterEnabledAndCloseBelowMA = i_emaFilterEnabled ? sig > md : true
colorVal = emaValue[1] > emaValue? color.red : color.green
plot(emaValue, title="EMA", color=colorVal, linewidth=2)
colorVal2 = emaValueForTrend[1] > emaValueForTrend? color.orange : color.lime
plot(emaValueForTrend, title="EMA", color=colorVal2, linewidth=2)
// ADX Filter
//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_adxFilterEnabled = input.bool(defval = false , title = "Enable ADX Filter", tooltip = "Enable if you would like to conditionally have entries incorporate ADX as a filter", group ="ADX Filter" )
i_adxVariant = input.string('ORIGINAL', title='ADX Variant', options=['ORIGINAL', 'MASANAKAMURA'], group ="ADX Filter" )
i_adxSmoothing = input.int(14, title="ADX Smoothing", group="ADX Filter")
i_adxDILength = input.int(14, title="DI Length", group="ADX Filter")
i_adxLowerThreshold = input.float(25, title="ADX Threshold", step=.5, group="ADX Filter")
calcADX_Masanakamura(int _len) =>
_smoothedTrueRange = 0.0
_smoothedDirectionalMovementPlus = 0.0
_smoothed_directionalMovementMinus = 0.0
_trueRange = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1])))
_directionalMovementPlus = high - nz(high[1]) > nz(low[1]) - low ? math.max(high - nz(high[1]), 0) : 0
_directionalMovementMinus = nz(low[1]) - low > high - nz(high[1]) ? math.max(nz(low[1]) - low, 0) : 0
_smoothedTrueRange := nz(_smoothedTrueRange[1]) - nz(_smoothedTrueRange[1]) / _len + _trueRange
_smoothedDirectionalMovementPlus := nz(_smoothedDirectionalMovementPlus[1]) - nz(_smoothedDirectionalMovementPlus[1]) / _len + _directionalMovementPlus
_smoothed_directionalMovementMinus := nz(_smoothed_directionalMovementMinus[1]) - nz(_smoothed_directionalMovementMinus[1]) / _len + _directionalMovementMinus
DIP = _smoothedDirectionalMovementPlus / _smoothedTrueRange * 100
DIM = _smoothed_directionalMovementMinus / _smoothedTrueRange * 100
_DX = math.abs(DIP - DIM) / (DIP + DIM) * 100
adx = ta.sma(_DX, _len)
[DIP, DIM, adx]
[DIPlusO, DIMinusO, ADXO] = ta.dmi(i_adxDILength, i_adxSmoothing)
[DIPlusM, DIMinusM, ADXM] = calcADX_Masanakamura(i_adxDILength)
adx = i_adxFilterEnabled and i_adxVariant == "ORIGINAL" ? ADXO : ADXM
bool isADXFilterEnabledAndAboveThreshold = i_adxFilterEnabled ? adx > i_adxLowerThreshold : true
///Start / End Time Periods
//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_startPeriodEnabled = input.bool(true, 'Start', group='Date Range', inline='Start Period')
i_startPeriodTime = input.time(timestamp('1 Jan 2019'), '', group='Date Range', inline='Start Period')
i_endPeriodEnabled = input.bool(true, 'End', group='Date Range', inline='End Period')
i_endPeriodTime = input.time(timestamp('31 Dec 2030'), '', group='Date Range', inline='End Period')
isStartPeriodEnabledAndInRange = i_startPeriodEnabled ? i_startPeriodTime <= time : true
isEndPeriodEnabledAndInRange = i_endPeriodEnabled ? i_endPeriodTime >= time : true
// Time-Of-Day Window
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// Inspired from https://www.tradingview.com/script/3BmID7aW-Highlight-Trading-Window-Simple-Hours-Time-of-Day-Filter/
i_timeFilterEnabled = input.bool(defval = true , title = "Enable Time-Of-Day Window", tooltip = "Limit the time of day for trade execution", group ="Time Window" )
i_KillzonesEnabled = input.bool(defval = false , title = "Use Killzones", tooltip = "Use London, NY AM and NY PM Killzones", group ="Time Window" )
i_timeZone = input.string(title="Select Local Time Zone", defval="GMT-4", options=["GMT-8","GMT-7", "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-2", "GMT-1", "GMT", "GMT+1", "GMT+2", "GMT+3","GMT+4","GMT+5","GMT+6","GMT+7","GMT+8","GMT+9","GMT+10","GMT+11","GMT+12","GMT+13"], group="Time Window")
i_betweenTime = input.session('0100-1545', title = "Time Window", group="Time Window") // '0000-0000' is anytime to enter
i_LunchTime = input.session('1200-1300', title = "Lunch Time Window", group="Time Window") // '0000-0000' is anytime to enter
i_AsiaKZTime = input.session('1930-0000', title = "Asia KZ Time Window", group="Time Window") // '0000-0000' is anytime to enter
i_LoKZTime = input.session('0200-0700', title = "London KZ Time Window", group="Time Window") // '0000-0000' is anytime to enter
i_NYAMKZTime = input.session('0800-1100', title = "NY AM Time Window", group="Time Window") // '0000-0000' is anytime to enter
i_NYPMKZTime = input.session('1400-1545', title = "NY PM Time Window", group="Time Window") // '0000-0000' is anytime to enter
isWithinWindowOfTime(_position) =>
currentTimeIsWithinWindowOfTime = not na(time(timeframe.period, _position + ':1234567', i_timeZone))
isTimeFilterEnabledAndInRange = false
if i_KillzonesEnabled
isTimeFilterEnabledAndInRange := i_timeFilterEnabled ? isWithinWindowOfTime(i_LoKZTime) or isWithinWindowOfTime(i_NYAMKZTime) or isWithinWindowOfTime(i_NYPMKZTime) : true
else
isTimeFilterEnabledAndInRange := i_timeFilterEnabled ? isWithinWindowOfTime(i_betweenTime) and not isWithinWindowOfTime(i_LunchTime) : true
isStartEndPeriodsAndTimeInRange = isStartPeriodEnabledAndInRange and isEndPeriodEnabledAndInRange and isTimeFilterEnabledAndInRange
// Trade Direction
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_tradeDirection = input.string('Long and Short', title='Trade Direction', options=['Long and Short', 'Long Only', 'Short Only'], group='Trade Direction')
// Start the Trade Logic here
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// Variables to be used for Long and Short
// Entry Variables
longCondition = false
shortCondition = false
// Exit Variables
closeLongCondition = false
closeShortCondition = false
// Stop Loss variables
slLongClose = false
slShortClose = false
// Percent as Points
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
per(pcnt) =>
strategy.position_size != 0 ? math.round(pcnt / 100 * strategy.position_avg_price / syminfo.mintick) : float(na)
// Take profit 1
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_takeProfitTargetPercent1 = input.float(title='Take Profit 1 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 1')
i_takeProfitQuantityPercent1 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 1')
// Take profit 2
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_takeProfitTargetPercent2 = input.float(title='Take Profit 2 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 2')
i_takeProfitQuantityPercent2 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 2')
// Take profit 3
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_takeProfitTargetPercent3 = input.float(title='Take Profit 3 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 3')
i_takeProfitQuantityPercent3 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 3')
// Take profit 4
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_takeProfitTargetPercent4 = input.float(title='Take Profit 4 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit')
/// Stop Loss
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_stopLossPercent = input.float(title='Stop Loss (%)', defval=999, minval=0.01, step=0.5, group='Stop Loss') * 0.01
// if tp_choice_fibstoploss == false
// //slLongClose := close < strategy.position_avg_price * (1 - i_stopLossPercent)
// //slShortClose := close > strategy.position_avg_price * (1 + i_stopLossPercent)
// slLongClose := close < strategy.position_avg_price - 2 // using a default $ value
// slShortClose := close > strategy.position_avg_price + 2
/// Leverage
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_leverage = input.float(1, 'Leverage', step=.5, group='Leverage')
i_percentOfEquityToTrade = input.float(100, "% of Equity to Stake Per Trade", minval=0.01, maxval=100, step=5, group='Leverage') * .01
contracts = 1 //(i_percentOfEquityToTrade * strategy.equity / close * i_leverage)
/// Stop Loss
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_TakeProfitValue = input.int(title='Take Profit in ticks', defval=40, minval=5, step=1, group='Stop Loss')
i_stopLossValue = input.int(title='Stop Loss in ticks', defval=10, minval=0, step=1, group='Stop Loss')
//i_TrailingstopValue = input.int(title='Trailing Stop Loss in ticks', defval=na, minval=0, step=1, group='Stop Loss')
float i_TrailingstopValue = na // Setting this to NA since it was making the Shorts exit immediately. Enable once this is fixed.
// look at trail_offset to fix this issue
/// Trade State Management
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
isInLongPosition = strategy.position_size > 0
isInShortPosition = strategy.position_size < 0
/// ProfitView Alert Syntax String Generation
//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_alertSyntaxPrefix = input.string(defval='CRYPTANEX_99FTX_Strategy-Name-Here', title='Alert Syntax Prefix', group='ProfitView Alert Syntax')
alertSyntaxBase = i_alertSyntaxPrefix + '\n#' + str.tostring(open) + ',' + str.tostring(high) + ',' + str.tostring(low) + ',' + str.tostring(close) + ',' + str.tostring(volume) + ','
var debugLong = array.new_int(1) // Using an array to enable setting of global variable from function
/// Trade Execution
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
longConditionCalc = (longCondition and isADXFilterEnabledAndAboveThreshold and isEMAFilterEnabledAndCloseAboveMA) //and ( inTransition == false) //or isEMATrendUp
shortConditionCalc = (shortCondition and isADXFilterEnabledAndAboveThreshold and isEMAFilterEnabledAndCloseBelowMA) //and ( inTransition == false) //or isEMATrendDown
//and isEMAFilterEnabledAndCloseBelowMA or isEMAFilterEnabledAndCloseAboveMA
//if( closeLongCondition and emaTrendUp)
// closeLongCondition := false
//if( closeShortCondition and emaTrendDown)
// closeShortCondition := false
//if( isInLongPosition and isEMAFilterEnabledAndCloseBelowMA)
// closeLongCondition := true
//if( isInShortPosition and isEMAFilterEnabledAndCloseAboveMA)
// closeShortCondition := true
//plotshape(longConditionCalc and i_tradeDirection != 'Short Only', style=shape.arrowdown,color=color.blue, location = location.bottom)
plotshape(longConditionCalc and isStartEndPeriodsAndTimeInRange and i_tradeDirection != 'Short Only' and isInLongPosition == false , style=shape.triangleup,color=color.green, location = location.belowbar, size = size.small)
plotshape(closeLongCondition and isInLongPosition , style=shape.xcross,color=color.fuchsia, location = location.abovebar, size = size.tiny)
plotshape(shortConditionCalc and isStartEndPeriodsAndTimeInRange and i_tradeDirection != 'Long Only' and isInShortPosition == false , style=shape.triangledown,color=color.red, location = location.abovebar, size = size.small)
plotshape(closeShortCondition and isInShortPosition , style=shape.xcross,color=color.red, location = location.belowbar, size = size.tiny)
plotshape(slLongClose and isInLongPosition and isEMATrendDown , style=shape.flag,color=color.blue, location = location.belowbar, size = size.tiny)
plotshape(slShortClose and isInShortPosition and isEMATrendUp , style=shape.flag,color=color.maroon, location = location.belowbar, size = size.tiny)
if isStartEndPeriodsAndTimeInRange
if longConditionCalc and i_tradeDirection != 'Short Only' and isInLongPosition == false
// Incase we still have a buy stop order in the market
strategy.cancel_all()
// Close any existing positions according to the rules
strategy.close_all()
//array.set(debugLong, 0, 1) // Make background yellow
strategy.entry('Long', strategy.long, qty=contracts)
strategy.exit("SL Long", "long", profit = i_TakeProfitValue, loss = i_stopLossValue, trail_points=i_TrailingstopValue,comment = "slValue Long") // generate full exit bracket (profit 10 points, loss 5 points per contract) from entry with name "long"
//strategy.exit("SL Long", from_entry = 'Long', stop = slValue, comment = "slValue Long")
alert(message=alertSyntaxBase + 'side:long', freq=alert.freq_once_per_bar_close)
if shortConditionCalc and i_tradeDirection != 'Long Only' and isInShortPosition == false
// Incase we still have a buy stop order in the market
strategy.cancel_all()
// Close any existing positions according to the rules
strategy.close_all()
strategy.entry('Short', strategy.short, qty=contracts)
strategy.exit("SL Short", "Short", profit = i_TakeProfitValue, loss = i_stopLossValue, trail_points=i_TrailingstopValue, comment = "slValue Short")
//strategy.exit("SL Short", from_entry = 'Short', stop = slValue, comment = "slValue Short")
alert(message=alertSyntaxBase + 'side:short', freq=alert.freq_once_per_bar_close)
else if isWithinWindowOfTime("1550-1800")
// This snippet is for closing all orders at EOD before market closes (Requirement for prop firms
// Incase we still have a buy stop order in the market
strategy.cancel_all()
// Close any existing positions according to the rules
strategy.close_all(comment = "EOD Close")
//Inspired from Multiple %% profit exits example by adolgo https://www.tradingview.com/script/kHhCik9f-Multiple-profit-exits-example/
strategy.exit('TP1', qty_percent=i_takeProfitQuantityPercent1, profit=per(i_takeProfitTargetPercent1))
strategy.exit('TP2', qty_percent=i_takeProfitQuantityPercent2, profit=per(i_takeProfitTargetPercent2))
strategy.exit('TP3', qty_percent=i_takeProfitQuantityPercent3, profit=per(i_takeProfitTargetPercent3))
strategy.exit('i_takeProfitTargetPercent4', profit=per(i_takeProfitTargetPercent4))
// Stop Loss
if(slLongClose and isInLongPosition )
strategy.close('Long', qty_percent=100, comment='SL Long')
if(slShortClose and isInShortPosition)
strategy.close('Short', qty_percent=100, comment='SL Short')
// Conditional Closes
if((closeLongCondition) and isInLongPosition )//and isEMATrendUp == false)
strategy.close('Long', qty_percent=100, comment='Close Long')
//array.set(debugLong, 0, 0) // Make background yellow
if((closeShortCondition) and isInShortPosition )//and isEMATrendDown == false) //and isEMAFilterEnabledAndCloseAboveMA or isEMAFilterEnabledAndCloseAboveMA
strategy.close('Short', qty_percent=100, comment='Close Short')
// Global Dashboard Variables
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// Dashboard Table Text Size
i_tableTextSize = input.string(title="Dashboard Size", defval="Small", options=["Auto", "Huge", "Large", "Normal", "Small", "Tiny"], group="Dashboards")
table_text_size(s) =>
switch s
"Auto" => size.auto
"Huge" => size.huge
"Large" => size.large
"Normal" => size.normal
"Small" => size.small
=> size.tiny
tableTextSize = table_text_size(i_tableTextSize)
/// Performance Summary Dashboard
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
// Inspired by https://www.tradingview.com/script/uWqKX6A2/ - Thanks VertMT
i_showDashboard = input.bool(title="Performance Summary", defval=true, group="Dashboards", inline="Show Dashboards")
f_fillCell(_table, _column, _row, _title, _value, _bgcolor, _txtcolor) =>
_cellText = _title + "\n" + _value
table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor, text_color=_txtcolor, text_size=tableTextSize)
// Draw dashboard table
if i_showDashboard
var bgcolor = color.new(color.black,0)
// Keep track of Wins/Losses streaks
newWin = (strategy.wintrades > strategy.wintrades[1]) and (strategy.losstrades == strategy.losstrades[1]) and (strategy.eventrades == strategy.eventrades[1])
newLoss = (strategy.wintrades == strategy.wintrades[1]) and (strategy.losstrades > strategy.losstrades[1]) and (strategy.eventrades == strategy.eventrades[1])
varip int winRow = 0
varip int lossRow = 0
varip int maxWinRow = 0
varip int maxLossRow = 0
if newWin
lossRow := 0
winRow := winRow + 1
if winRow > maxWinRow
maxWinRow := winRow
if newLoss
winRow := 0
lossRow := lossRow + 1
if lossRow > maxLossRow
maxLossRow := lossRow
// Prepare stats table
var table dashTable = table.new(position.top_right, 1, 15, border_width=1)
if barstate.islastconfirmedhistory
// Update table
dollarReturn = strategy.netprofit
f_fillCell(dashTable, 0, 0, "Start:", str.format("{0,date,long}", strategy.closedtrades.entry_time(0)) , bgcolor, color.white) // + str.format(" {0,time,HH:mm}", strategy.closedtrades.entry_time(0))
f_fillCell(dashTable, 0, 1, "End:", str.format("{0,date,long}", strategy.opentrades.entry_time(0)) , bgcolor, color.white) // + str.format(" {0,time,HH:mm}", strategy.opentrades.entry_time(0))
_profit = (strategy.netprofit / strategy.initial_capital) * 100
f_fillCell(dashTable, 0, 2, "Net Profit:", str.tostring(_profit, '##.##') + "%", _profit > 0 ? color.teal : color.maroon, color.white)
_numOfDaysInStrategy = (strategy.opentrades.entry_time(0) - strategy.closedtrades.entry_time(0)) / (1000 * 3600 * 24)
f_fillCell(dashTable, 0, 3, "Percent Per Day", str.tostring(_profit / _numOfDaysInStrategy, '#########################.#####')+"%", _profit > 0 ? color.teal : color.maroon, color.white)
_winRate = ( strategy.wintrades / strategy.closedtrades ) * 100
f_fillCell(dashTable, 0, 4, "Percent Profitable:", str.tostring(_winRate, '##.##') + "%", _winRate < 50 ? color.maroon : _winRate < 75 ? #999900 : color.teal, color.white)
f_fillCell(dashTable, 0, 5, "Profit Factor:", str.tostring(strategy.grossprofit / strategy.grossloss, '##.###'), strategy.grossprofit > strategy.grossloss ? color.teal : color.maroon, color.white)
f_fillCell(dashTable, 0, 6, "Total Trades:", str.tostring(strategy.closedtrades), bgcolor, color.white)
f_fillCell(dashTable, 0, 8, "Max Wins In A Row:", str.tostring(maxWinRow, '######') , bgcolor, color.white)
f_fillCell(dashTable, 0, 9, "Max Losses In A Row:", str.tostring(maxLossRow, '######') , bgcolor, color.white)
// Monthly Table Performance Dashboard By @QuantNomad
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
i_showMonthlyPerformance = input.bool(true, 'Monthly Performance', group='Dashboards', inline="Show Dashboards")
i_monthlyReturnPercision = 2
if i_showMonthlyPerformance
new_month = month(time) != month(time[1])
new_year = year(time) != year(time[1])
eq = strategy.equity
bar_pnl = eq / eq[1] - 1
cur_month_pnl = 0.0
cur_year_pnl = 0.0
// Current Monthly P&L
cur_month_pnl := new_month ? 0.0 :
(1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1
// Current Yearly P&L
cur_year_pnl := new_year ? 0.0 :
(1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1
// Arrays to store Yearly and Monthly P&Ls
var month_pnl = array.new_float(0)
var month_time = array.new_int(0)
var year_pnl = array.new_float(0)
var year_time = array.new_int(0)
last_computed = false
if (not na(cur_month_pnl[1]) and (new_month or barstate.islastconfirmedhistory))
if (last_computed[1])
array.pop(month_pnl)
array.pop(month_time)
array.push(month_pnl , cur_month_pnl[1])
array.push(month_time, time[1])
if (not na(cur_year_pnl[1]) and (new_year or barstate.islastconfirmedhistory))
if (last_computed[1])
array.pop(year_pnl)
array.pop(year_time)
array.push(year_pnl , cur_year_pnl[1])
array.push(year_time, time[1])
last_computed := barstate.islastconfirmedhistory ? true : nz(last_computed[1])
// Monthly P&L Table
var monthly_table = table(na)
if (barstate.islastconfirmedhistory)
monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1)
table.cell(monthly_table, 0, 0, "", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 1, 0, "Jan", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 2, 0, "Feb", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 3, 0, "Mar", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 4, 0, "Apr", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 5, 0, "May", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 6, 0, "Jun", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 7, 0, "Jul", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 8, 0, "Aug", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 9, 0, "Sep", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 10, 0, "Oct", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 11, 0, "Nov", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 12, 0, "Dec", bgcolor = #cccccc, text_size=tableTextSize)
table.cell(monthly_table, 13, 0, "Year", bgcolor = #999999, text_size=tableTextSize)
for yi = 0 to array.size(year_pnl) - 1
table.cell(monthly_table, 0, yi + 1, str.tostring(year(array.get(year_time, yi))), bgcolor = #cccccc, text_size=tableTextSize)
y_color = array.get(year_pnl, yi) > 0 ? color.new(color.teal, transp = 40) : color.new(color.gray, transp = 40)
table.cell(monthly_table, 13, yi + 1, str.tostring(math.round(array.get(year_pnl, yi) * 100, i_monthlyReturnPercision)), bgcolor = y_color, text_color=color.new(color.white, 0),text_size=tableTextSize)
for mi = 0 to array.size(month_time) - 1
m_row = year(array.get(month_time, mi)) - year(array.get(year_time, 0)) + 1
m_col = month(array.get(month_time, mi))
m_color = array.get(month_pnl, mi) > 0 ? color.new(color.teal, transp = 40) : color.new(color.maroon, transp = 40)
table.cell(monthly_table, m_col, m_row, str.tostring(math.round(array.get(month_pnl, mi) * 100, i_monthlyReturnPercision)), bgcolor = m_color, text_color=color.new(color.white, 0), text_size=tableTextSize)