Repository navigation
Expand file tree
/
Copy pathTO_Method_v4.cpp
More file actions
4249 lines (3818 loc) · 199 KB
/
Copy pathTO_Method_v4.cpp
File metadata and controls
4249 lines (3818 loc) · 199 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
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// ============================================================================================
// TraderOracle Method v4, build 6 - Oct 4, 2026
// ============================================================================================
// HISTORY: I fed 208 reversal indicators into Fable 5.1 Max, with instructions to parse them
// all, backtest over 10 years market data, and combine into a single, SUPER REVERSAL indicator.
// Then I fed in LittleRizzy code, and my own Reversal Volume Patterns.
//
// Values in <angle brackets> are constants in the HOLY GRAIL REVERSALS settings block below.
//
// BULLISH signal at the close of bar i (bearish is the exact mirror image):
//
// 1. LOCATION Low[i] is the lowest low of the last <Extreme Lookback> bars.
//
// 2. VETOES ("don't catch the knife" - each of these made reversals WORSE in testing)
// - any close in the last 3 bars more than <Band Veto> std devs below its
// 20-bar mean (a band blow-through is momentum, not exhaustion)
// - the signal bar's range is more than <Wide-Range Veto> x ATR
// - any of the last 3 bars has volume more than <Climax Veto> x average
//
// 3. SCORE one point each, 0..4
// + Persistence : a TD-style count of consecutive closes below the close
// 4 bars earlier reached <Persistence Count> in the last 5 bars
// + Divergence : the new low undercuts the prior swing low (bars i-30..i-6)
// while the Bollinger %B z-score is HIGHER than it was there
// + Quiet volume: relative volume at the new low is below <Quiet Threshold>
// (selling drying up beat climax volume in every test set)
// + Trend side : close is above the 200 EMA (buying a dip in an uptrend)
//
// 4. FIRE score >= <Minimum Score> and no buy signal in the previous <Cooldown> bars.
// Score 4 is plotted with the larger "A+" arrow.
//
// The signal fires on the extreme bar itself. Waiting for a breakout above the signal bar
// (the "confirmation" used by several of the source indicators) consistently gave back the
// edge in testing, so there is deliberately no confirmation delay.
//
// Stop = signal-bar low - <Stop Buffer> x ATR (risk floored at <Min Risk> x ATR)
// Target= close + <Target R> x risk
// Each signal is tracked for up to <Max Bars To Track> bars until its stop or target is hit.
//
// ALERTS (each one: Off / Buys only / Sells only / Buys and sells, plus its own sound number)
// 1. Signal arrow - an arrow appears.
// 2. Target hit - price reaches a signal's target before its stop. Fires the
// moment the target is touched. If one bar contains both the
// stop and the target, bar data can't tell which came first:
// live, the target counts only if it was touched while the stop
// was still untouched; after a chart reload such a bar counts as
// a stop-out.
// 3. Open = prior close - an arrow appears AND the signal bar opened at the previous
// bar's close (within <Tolerance> ticks).
// 4. Open = prior close + band break
// - as 3, AND the signal bar or the bar before it broke the outer
// band on the signal's side (lower band for buys, upper band for
// sells). "Broke" = wick beyond the band by default, or close
// beyond it. The band is the alert Bollinger band by default, or
// the inner edge of the Resistance Cloud ("Alert 4 Band").
// 5. Trampoline - a TraderOracle trampoline completes (see below).
// 6. Engulfing at band - a TraderOracle engulfing candle at the Bollinger band.
// 7. Squeeze dot - a TraderOracle squeeze relaxer buy or sell dot.
// 8. Large wick in cloud - TraderOracle Method "Large Wick in Cloud": a red bar whose lower
// wick is longer than its body, with its low inside the lower
// cloud (buy); a green bar with a long upper wick into the upper
// cloud (sell).
// 9. Squeeze dot in cloud - a squeeze dot on a bar that reached the cloud on its side.
// 10. Trampoline in cloud - a trampoline whose three bars reached the cloud on its side
// (the TraderOracle Method script pairs buys with the UPPER cloud,
// which almost never happens; here buys pair with the lower cloud).
// Events found in the same update are combined into one Alert Manager entry; its sound is
// the most specific alert that matched (4 > 3 > 1 > 2 > 10 > 9 > 8 > 5 > 6 > 7). Sound
// number 0 = log entry only. Alerts 5-10 are off by default. Alerts never fire while the
// chart is loading or recalculating.
//
// RESISTANCE CLOUD (the outer bands of the TraderOracle Method script)
// The Nadaraya-Watson envelope (non-repainting, jdehorty KernelFunctions v2) exactly as the
// script computes it: a rational-quadratic kernel average of close / high / low, an ATR
// (Wilder, <Cloud ATR Length>) of those smoothed series, inner edge = average +/- <Near ATR
// Factor> x that ATR, outer edge = halfway between the near and far (<Far ATR Factor>)
// bounds. Note: the kernel averages <Start Regression At Bar> + 2 bars (32 by default) - that
// is how the library's loop is written - and the 256 lookback only sets how evenly those bars
// are weighted. In testing the cloud did not improve the signals (signals with and
// without a cloud touch performed the same), so it is context, not part of the score; the
// large-wick-in-cloud setup had a small, consistent edge on its own (the same wick outside
// the cloud had none).
//
// TRADERORACLE PATTERNS (separate markers; they do not change the signal score)
// Ported from the TraderOracle module and computed with the same Sierra Chart functions
// (sc.RSI simple 14, sc.BollingerBands 20/2 simple, the squeeze relaxer EMA/linear
// regression sequence), so they line up with its Olympus / Trampoline studies. In testing
// none of the three had an edge on its own, and none reliably improved the signals.
// - Trampoline: bearish = green bar at the upper band, then two red bars with a lower close,
// RSI > 80 on one of the three bars; bullish is the mirror (RSI < 20, lower band).
// "As in TraderOracle" reproduces the module exactly: a bug there makes the band check
// almost always pass. "Require band touch" applies the band check as intended (1 tick).
// Marked on the bar that completes the pattern (TraderOracle labels the bar before it).
// - Engulfing at band (Olympus "Engulfing Green/Red BB"): a green (red) bar with a bigger
// body than the previous bar, where both bars' lows (highs) are below (above) the
// current lower (upper) band; doji bars skipped. Shown as a background highlight.
// Optional: TraderOracle's classic engulfing test, at the band or anywhere.
// - Squeeze dot (Olympus "Squeeze Relaxer"): the squeeze momentum histogram turns up while
// at or below zero (buy) or down while at or above zero (sell); dots alternate buy/sell.
//
// MARKER STYLE
// Labels (default): tags drawn with Sierra Chart chart drawings. Regular signals are bold
// coloured text with no background - "BUY" below the bar, "SELL" above it. A+ (4/4)
// signals get a filled tag, "BUY+" / "SELL+", with a soft glow behind the bar.
// <Signal Tag Text> can say LONG / SHORT instead. <Pin Stem> hangs the tag on a thin stem
// below / above the bar. Filled "TR" tags for trampolines; squeeze dots (small dots, off by
// default - "Show Squeeze Dots"). One tag per side per bar. Colours come from the colour
// theme (see COLOR THEMES); text on filled tags is picked automatically for contrast.
// Classic shapes (USE_LABEL_TAGS = false): the original subgraph arrows, triangles, stars and squares.
// The "Signal" subgraph (+score for buys, -score for sells) is filled in both styles for
// use in alert formulas, the Spreadsheet study or automated trading.
//
// Non-repainting: with "Evaluate On Bar Close Only" = Yes (default) a signal is only ever
// set on a completed bar and never changes afterwards.
//
// Subgraphs "Bull Score" / "Bear Score" carry the 0-4 score on qualifying extreme bars and
// can be referenced from other studies, the Spreadsheet study, or automated trading.
// ============================================================================================
#include "sierrachart.h"
#include <math.h>
#include <vector>
#include <chrono>
SCDLLName("TO Method v4")
// =============================================================================================
// =============================================================================================
//
// TO Method v4 - SETTINGS
//
// These used to be study inputs. They are fixed here so the signal is the one that was
// tested. To change one, edit the value, rebuild the study (Analysis >> Build Custom Studies
// DLL) and reload the chart. Float values need the trailing "f".
//
// =============================================================================================
// =============================================================================================
namespace TOMethod4
{
// ---------------------------------------------------------------- the reversal signal
const int EXTREME_LOOKBACK_BARS = 20; // signal bar must be the lowest low (buy) / highest high (sell) of this many bars
const int MIN_SCORE_TO_SIGNAL = 3; // 1-4. 3 = default, 2 = ~2.5x more signals with a smaller edge, 4 = A+ only
const int PERSISTENCE_COUNT = 6; // closes beyond the close 4 bars back (TD-style count) needed for the persistence point
const int DIVERGENCE_WINDOW_START = 30; // prior-swing window for the %B divergence point: from this many bars back...
const int DIVERGENCE_WINDOW_END = 6; // ...to this many bars back
const int ZSCORE_BOLLINGER_LENGTH = 20; // Bollinger length for the %B z-score (divergence point and blow-through veto)
const bool USE_VOLUME = true; // quiet-volume point and climax-volume veto
const int VOLUME_AVERAGE_LENGTH = 20;
const float QUIET_VOLUME_THRESHOLD = 1.0f; // x average volume: below this at the new extreme = quiet-volume point
const float CLIMAX_VOLUME_VETO = 2.5f; // x average volume: any of the last 3 bars above this = no signal
const int TREND_EMA_LENGTH = 200; // trend-side point: buys above / sells below this EMA
const float BAND_BLOWTHROUGH_VETO = 3.0f; // std devs: a close this far outside its 20-bar mean in the last 3 bars = no signal
const float WIDE_RANGE_BAR_VETO = 1.6f; // x ATR: a signal bar wider than this = no signal
const int ATR_LENGTH = 14;
const int COOLDOWN_BARS = 5; // bars between same-side signals
const float STOP_BUFFER_ATR = 0.1f; // stop = signal-bar extreme -/+ this x ATR
const float MIN_RISK_ATR = 0.3f; // risk is at least this x ATR
const float TARGET_R = 1.5f; // target = entry +/- this x risk
const bool SHOW_STOP_TARGET_LINES = false; // dashes at the latest signal's stop and target until one is hit
const float TAG_OFFSET_ATR = 0.3f; // distance of the BUY / SELL tag from the bar (x ATR)
const bool EVALUATE_ON_BAR_CLOSE = false; // true = non-repainting: signals only on completed bars
// ---------------------------------------------------------------- alert bands (alerts 3 and 4)
const int OPEN_EQ_TOLERANCE_TICKS = 0; // "open = prior close" within this many ticks (0 = exact)
const int ALERT_BB_LENGTH = 20;
const float ALERT_BB_STDDEV = 2.0f;
const bool BAND_BREAK_ON_CLOSE = false; // false = a wick beyond the band counts, true = needs a close beyond it
const bool SHOW_ALERT_BANDS = true;
const bool MARK_OPEN_EQ_SIGNALS = true; // diamond at the open of open = prior close signals
// ---------------------------------------------------------------- TraderOracle patterns
const bool SHOW_TRAMPOLINE = true;
const int TRAMPOLINE_BAND_CHECK = 0; // 0 = as in TraderOracle (band check almost always passes), 1 = require band touch
const int TRAMPOLINE_RSI_OVERBOUGHT = 80;
const int TRAMPOLINE_RSI_OVERSOLD = 20;
const bool SHOW_ENGULFING = true;
const int ENGULFING_RULE = 0; // 0 = Olympus Engulfing BB, 1 = classic engulfing beyond band, 2 = classic anywhere
const bool ENGULFING_SKIP_DOJI = true;
const int SQUEEZE_LENGTH = 20;
// ---------------------------------------------------------------- chart tags
const bool USE_LABEL_TAGS = true; // true = text tags (BUY / SELL / BUY+ ...), false = classic subgraph arrows
const int LABEL_FONT_SIZE = 8;
const char* const LABEL_FONT = "Segoe UI";
const bool GLOW_BEHIND_A_PLUS = true;
// ---------------------------------------------------------------- Resistance Cloud (TraderOracle Method outer bands)
const int CLOUD_KERNEL_LOOKBACK = 256; // script "Lookback Window"
const float CLOUD_RELATIVE_WEIGHT = 3.5f; // script "Relative Weighting"
const int CLOUD_START_AT_BAR = 30; // script "Start Regression at Bar" (the kernel averages this + 2 bars)
const int CLOUD_ATR_LENGTH = 66;
const float CLOUD_NEAR_ATR_FACTOR = 1.95f; // inner edge of the cloud
const float CLOUD_FAR_ATR_FACTOR = 7.0f; // outer edge = halfway between the near and far bounds
}
// =============================================================================================
namespace
{
inline double UrsMax(double a, double b) { return a > b ? a : b; }
inline int UrsMaxI(int a, int b) { return a > b ? a : b; }
inline int UrsMinI(int a, int b) { return a < b ? a : b; }
// Bollinger z-score of the close at bar k (population std dev, like Pine ta.stdev).
bool ZScoreAt(SCStudyInterfaceRef sc, int k, int length, double& z)
{
if (k < length - 1)
return false;
double sum = 0.0;
for (int j = k - length + 1; j <= k; ++j)
sum += sc.Close[j];
const double mean = sum / length;
double ss = 0.0;
for (int j = k - length + 1; j <= k; ++j)
{
const double d = sc.Close[j] - mean;
ss += d * d;
}
const double sd = sqrt(ss / length);
if (sd <= 0.0)
return false;
z = (sc.Close[k] - mean) / sd;
return true;
}
// Volume at bar k relative to its simple average over `length` bars.
bool RelVolumeAt(SCStudyInterfaceRef sc, int k, int length, double& rvol)
{
if (k < length - 1)
return false;
double sum = 0.0;
for (int j = k - length + 1; j <= k; ++j)
sum += sc.Volume[j];
if (sum <= 0.0)
return false;
rvol = sc.Volume[k] / (sum / length);
return true;
}
double TrueRange(SCStudyInterfaceRef sc, int j)
{
const double hl = sc.High[j] - sc.Low[j];
if (j == 0)
return hl;
const double hc = fabs(sc.High[j] - sc.Close[j - 1]);
const double lc = fabs(sc.Low[j] - sc.Close[j - 1]);
return UrsMax(hl, UrsMax(hc, lc));
}
// Alert kinds, ordered by specificity: when several match in one update, the highest
// one supplies the sound.
enum
{
URS_ALERT_SQUEEZE = 0, // alert 7
URS_ALERT_ENGULF = 1, // alert 6
URS_ALERT_TRAMP = 2, // alert 5
URS_ALERT_WICK_CLOUD = 3, // alert 8
URS_ALERT_SQUEEZE_CLOUD = 4, // alert 9
URS_ALERT_TRAMP_CLOUD = 5, // alert 10
URS_ALERT_TARGET = 6, // alert 2
URS_ALERT_SIGNAL = 7, // alert 1
URS_ALERT_OPEN_EQ = 8, // alert 3
URS_ALERT_OPEN_EQ_BAND = 9, // alert 4
URS_ALERT_KINDS = 10
};
// Direction dropdown: 0 = Off, 1 = Buys only, 2 = Sells only, 3 = Buys and sells
inline bool DirectionOn(int setting, bool isBuy)
{
return setting == 3 || (setting == 1 && isBuy) || (setting == 2 && !isBuy);
}
const int URS_MAX_EVENTS = 64;
struct AlertEvent
{
bool IsTarget; // target-hit event (else a signal event)
int Dir; // 0 = buy, 1 = sell
int SignalBar;
int KindMask; // alert kinds being reported
int Priority;
int Index; // bar index the alert is attached to
SCString Text;
};
// Persistent-int keys
const int PKEY_LAST_ALERTED_BASE = 100; // 100..119: last bar alerted, per kind and direction
const int PKEY_ALERTED_LAST_CALL = 20;
const int PKEY_LAST_ALERT_INDEX = 21;
const int PKEY_PENDING_FROM = 22; // earliest bar of events deferred to the next update (-1 = none)
const int PKEY_EXT_SOUND = 23; // sound of other modules' alerts carried to the next update
const int PKEY_EXT_TEXT = 1; // (persistent string) their text
}
// =============================================================================================
// Alerts raised by the Little Rizzy module during an update. They are sent together with the
// signal module's alerts as one Alert Manager entry at the end of the update.
// =============================================================================================
struct RG_ExternalAlerts
{
enum { MAX = 16 };
int Count = 0;
int Sound[MAX];
SCString Text[MAX];
void Add(int sound, const char* text)
{
if (Count >= MAX)
return;
Sound[Count] = sound;
Text[Count] = text;
++Count;
}
void Add(int sound, const SCString& text) { Add(sound, text.GetChars()); }
};
// Subgraph and input numbers of each module (inputs are numbered without gaps).
const int RG_SG_LITTLE_RIZZY = 34;
const int RG_SG_VOLUME_PATTERN = 51;
// Inputs are listed in Study Settings in index order, so Color Theme (0-1) comes first.
const int RG_IN_SEP_THEME = 0;
const int RG_IN_THEME = 1;
const int RG_IN_SEP_GRAIL = 2;
const int RG_IN_GRAIL = 3; // 30 inputs: 3..32
const int RG_IN_SEP_RIZZY = 33;
const int RG_IN_RIZZY = 34; // 13 inputs: 34..46
const int RG_IN_SEP_VOLUME = 47;
const int RG_IN_VOLUME = 48; // 2 inputs: 48..49
// =============================================================================================
// =============================================================================================
//
// COLOR THEMES
//
// The "Color Theme" input (first section of the inputs) colours every marker of the three
// modules. Each theme is built on one colour scheme:
// - BUY and SELL are a complementary (or split-complementary) pair.
// - BUY+ / SELL+ (A+ tags and their glow) are a stronger shade of the same hue.
// - Trampoline, squeeze, volume-pattern and target colours take the remaining positions
// around the colour wheel, so each kind of marker has its own hue.
// - The Resistance Cloud is a muted pair, so the bright tags stay readable on top of it.
// Engulfing backgrounds are faint tints of the cloud colours, blended toward the
// chart background, and the cloud's outer lines are a darker shade of its inner lines.
// - Little Rizzy broken lines are a neutral grey tinted toward the target colour, and
// the touch blink is a near-white (dark chart) or near-black (light chart) flash.
//
// Themes marked (dark) are tuned for a dark chart background, (light) for a white or light
// one. "Custom" leaves every colour as it is in Study Settings >> Subgraphs (and the Little
// Rizzy "Broken / Expired Target Line Color" inputs). Those start as the last theme's
// colours, so pick the closest theme first, then switch to Custom to fine-tune.
//
// To add or change a theme, edit RG_THEMES and RG_THEME_NAMES together (same order),
// then rebuild.
//
// =============================================================================================
// =============================================================================================
struct RG_Theme
{
COLORREF Buy, Sell; // BUY / SELL tags (classic: arrows)
COLORREF BuyPlus, SellPlus; // BUY+ / SELL+ filled tags and their glow (classic: A+ arrows)
COLORREF Trampoline; // TR tags, both sides (classic: triangles)
COLORREF Squeeze; // squeeze dots, both sides
COLORREF Volume; // Reversal Volume Patterns squares, both sides
COLORREF Target; // Little Rizzy target lines (classic: target-hit squares)
COLORREF Expired; // Little Rizzy expired target lines and invalidated-setup dots
COLORREF CloudUpper; // Resistance Cloud above price
COLORREF CloudLower; // Resistance Cloud below price
};
static const RG_Theme RG_THEMES[] =
{
// Buy Sell Buy+ Sell+ TR Squeeze Volume Target Expired Cloud upper Cloud lower
// 1. Classic Neon (dark): the original colours, TR in red
{ RGB( 0,230,255), RGB(255, 60,170), RGB( 0,230,255), RGB(255, 60,170), RGB(230, 30, 30), RGB(255,196, 0), RGB( 0,128,255), RGB(252,236,188), RGB(176, 73, 14), RGB(224, 49, 73), RGB( 0,168,107) },
// 2. Midnight Ocean (dark): turquoise / coral complements, gold, lavender, cornflower
{ RGB( 64,224,208), RGB(255,127, 80), RGB( 0,245,212), RGB(255, 99, 64), RGB(255,214,102), RGB(180,160,255), RGB( 77,148,255), RGB(200,230,255), RGB(150, 90, 70), RGB(190, 90, 80), RGB( 40,140,150) },
// 3. Emerald & Ruby (dark): jewel tones - emerald, ruby, topaz, amethyst, sapphire, pearl
{ RGB( 46,204,113), RGB(230, 57, 90), RGB( 0,230,118), RGB(255, 40, 90), RGB(241,196, 15), RGB(155, 89,182), RGB( 52,152,219), RGB(236,240,241), RGB(140,100, 60), RGB(150, 50, 70), RGB( 30,120, 90) },
// 4. Solarized Dark: blue / orange complements on the Solarized accent wheel
{ RGB( 38,139,210), RGB(203, 75, 22), RGB( 80,165,235), RGB(230,100, 40), RGB(211, 54,130), RGB(181,137, 0), RGB( 42,161,152), RGB(238,232,213), RGB(101,123,131), RGB(170, 60, 55), RGB( 90, 95,160) },
// 5. Nord Aurora (dark): Nord aurora green / red with frost blue, mauve and sand
{ RGB(163,190,140), RGB(191, 97,106), RGB(143,214,120), RGB(220, 90,100), RGB(180,142,173), RGB(235,203,139), RGB(136,192,208), RGB(236,239,244), RGB(160,105, 85), RGB(150, 85, 95), RGB( 94,129,172) },
// 6. Dracula (dark): Dracula green / red, purple, yellow, cyan, orange
{ RGB( 80,250,123), RGB(255, 85, 85), RGB( 40,220,100), RGB(255, 60, 60), RGB(189,147,249), RGB(241,250,140), RGB(139,233,253), RGB(255,184,108), RGB(150,110, 80), RGB(190, 80,140), RGB(130,105,190) },
// 7. Monokai (dark): lime / hot pink, orange, purple, sky, white
{ RGB(166,226, 46), RGB(249, 38,114), RGB(140,210, 20), RGB(230, 20, 95), RGB(253,151, 31), RGB(174,129,255), RGB(102,217,239), RGB(248,248,242), RGB(150,120, 90), RGB(150, 70,110), RGB( 70,130,150) },
// 8. Gruvbox (dark): warm retro - aqua / red, mauve, yellow, blue, cream
{ RGB(142,192,124), RGB(251, 73, 52), RGB(120,200, 95), RGB(255,100, 70), RGB(211,134,155), RGB(250,189, 47), RGB(120,160,200), RGB(235,219,178), RGB(175, 90, 30), RGB(165,100, 60), RGB( 69,133,136) },
// 9. Tokyo Night (dark): teal / rose, violet, gold, green, periwinkle white
{ RGB(115,218,202), RGB(247,118,142), RGB( 80,235,205), RGB(255, 95,125), RGB(187,154,247), RGB(224,175,104), RGB(158,206,106), RGB(235,236,245), RGB(170,110, 75), RGB(170, 90,120), RGB( 70,110,180) },
// 10. Catppuccin Mocha (dark): soft pastels - green / red, peach, mauve, sapphire, cream
{ RGB(166,227,161), RGB(243,139,168), RGB(130,220,125), RGB(240,110,150), RGB(250,179,135), RGB(203,166,247), RGB(116,199,236), RGB(249,226,175), RGB(160,130,120), RGB(180,110,140), RGB( 90,150,170) },
// 11. Terminal Amber (dark): trading-terminal green / red with amber, violet, blue
{ RGB( 60,220,100), RGB(255, 70, 70), RGB( 0,255,110), RGB(255, 40, 40), RGB(255,176, 0), RGB(200,120,255), RGB( 70,140,255), RGB(235,235,235), RGB(140,100, 40), RGB(150, 50, 50), RGB( 40,120, 70) },
// 12. Cyberpunk (dark): neon mint / magenta, electric blue, yellow, violet, orange
{ RGB( 0,255,159), RGB(255, 0,110), RGB( 60,255,190), RGB(255, 60,150), RGB( 0,184,255), RGB(252,238, 10), RGB(189, 0,255), RGB(255,140, 0), RGB(110, 60,130), RGB(150, 20, 90), RGB( 20,110,150) },
// 13. Aurora Borealis (dark): mint / pink, violet, pale gold, sky, ice
{ RGB(120,255,200), RGB(255,110,180), RGB( 60,240,170), RGB(240, 80,160), RGB(180,130,255), RGB(255,230,120), RGB( 90,170,255), RGB(210,240,255), RGB(120,100,150), RGB(130, 70,150), RGB( 40,130,120) },
// 14. Sunset Boulevard (dark): gold / coral warm pair, cool violet, sky and teal accents
{ RGB(255,200, 87), RGB(255, 94, 98), RGB(255,175, 40), RGB(255, 60, 80), RGB(170,120,255), RGB(100,210,255), RGB( 0,200,170), RGB(235,225,245), RGB(130, 90, 70), RGB(170, 70, 90), RGB(150,120, 60) },
// 15. Steel & Copper (dark): steel blue / copper, orchid, brass, patina, silver
{ RGB(110,180,230), RGB(230,130, 80), RGB( 70,160,240), RGB(240,110, 50), RGB(190,120,220), RGB(230,200,120), RGB(120,200,170), RGB(220,225,230), RGB(130, 90, 70), RGB(150, 90, 70), RGB( 70,110,140) },
// 16. Forest Canopy (dark): leaf / rust, heather, wheat, river blue, mist
{ RGB(140,200, 90), RGB(215,100, 70), RGB(110,190, 60), RGB(230, 80, 50), RGB(180,140,220), RGB(240,210,110), RGB(100,170,200), RGB(215,225,235), RGB(120, 95, 70), RGB(140, 80, 60), RGB( 60,110, 70) },
// 17. Royal Velvet (dark): gold / violet complements, crimson, jade, royal blue, ivory
{ RGB(255,200, 70), RGB(200,110,255), RGB(255,180, 20), RGB(180, 80,255), RGB(255,100,120), RGB(100,230,200), RGB( 90,150,255), RGB(245,235,215), RGB(130, 80,100), RGB(130, 70,150), RGB(150,120, 50) },
// 18. Graphite (dark): minimal - green / red accents, white TR, muted gold, slate, soft lilac
{ RGB( 64,214,160), RGB(240, 96, 96), RGB( 30,190,135), RGB(225, 70, 70), RGB(230,230,230), RGB(210,180,100), RGB(100,150,220), RGB(185,175,215), RGB(110,110,110), RGB(120, 95,100), RGB( 90,110,115) },
// 19. Vaporwave (dark): cyan / pink, lemon, mint, purple, peach
{ RGB( 1,205,254), RGB(255,113,206), RGB( 0,170,255), RGB(255, 70,190), RGB(255,251,150), RGB( 5,255,161), RGB(185,103,255), RGB(255,190,120), RGB(120, 80,130), RGB(170, 70,150), RGB( 60, 90,170) },
// 20. Tropical (dark): jade / watermelon, mango, orchid, lagoon, sand
{ RGB( 0,220,160), RGB(255, 90, 95), RGB( 0,200,140), RGB(255, 60, 70), RGB(255,200, 0), RGB(190,120,255), RGB( 0,160,255), RGB(255,240,210), RGB(150,100, 60), RGB(170, 70, 90), RGB( 30,120,150) },
// 21. Twilight Rose (dark): sage / rose, apricot, lilac, aqua, blush
{ RGB(150,215,170), RGB(240,120,160), RGB(110,210,150), RGB(240, 80,140), RGB(255,190,110), RGB(190,150,255), RGB(100,200,220), RGB(245,225,230), RGB(130, 90,110), RGB(150, 80,120), RGB( 80,130,110) },
// 22. Color-Safe (dark): Okabe-Ito palette, readable with colour-vision deficiency
{ RGB( 86,180,233), RGB(235,110, 20), RGB( 40,160,230), RGB(213, 94, 0), RGB(204,121,167), RGB(240,228, 66), RGB( 0,158,115), RGB(230,230,230), RGB(150,120, 60), RGB(180, 90, 40), RGB( 0,114,178) },
// 23. Paper Classic (light): deep green / crimson, orange, purple, blue, dark gold
{ RGB( 0,140, 90), RGB(200, 30, 50), RGB( 0,120, 75), RGB(180, 20, 40), RGB(230,110, 0), RGB(120, 60,180), RGB( 20, 90,200), RGB(150,120, 40), RGB(170,140,130), RGB(210, 90,100), RGB( 60,160,120) },
// 24. Solarized Light: blue / red, magenta, yellow, cyan, slate
{ RGB( 38,139,210), RGB(220, 50, 47), RGB( 20,110,190), RGB(200, 30, 30), RGB(211, 54,130), RGB(181,137, 0), RGB( 42,161,152), RGB( 88,110,117), RGB(147,161,161), RGB(210,110, 80), RGB(108,113,196) },
// 25. Salmon Paper (light): financial-paper jade / claret, mandarin, velvet, oxford blue, slate
{ RGB( 0,153, 77), RGB(153, 15, 61), RGB( 0,130, 65), RGB(204, 0, 0), RGB(225,105, 20), RGB( 89, 51,128), RGB( 15, 84,153), RGB( 38, 42, 51), RGB(190,160,140), RGB(204,120,140), RGB(120,170, 60) },
// 26. Nordic Light: moss / rose, ochre, heather, frost blue, polar slate
{ RGB(100,140, 80), RGB(191, 97,106), RGB( 80,125, 60), RGB(170, 70, 80), RGB(190,120, 30), RGB(150,100,150), RGB( 94,129,172), RGB( 76, 86,106), RGB(170,150,130), RGB(200,130,135), RGB(110,150,170) },
// 27. Ink & Coral (light): ink teal / coral, purple, mustard, forest green, graphite
{ RGB( 0,110,130), RGB(230, 90, 70), RGB( 0, 90,110), RGB(210, 60, 45), RGB(140, 50,170), RGB(180,130, 0), RGB( 60,140, 60), RGB( 90, 90,100), RGB(190,150,140), RGB(220,140,120), RGB( 90,160,170) },
// 28. Earth Tones (light): olive / terracotta, denim, ochre, heather, umber
{ RGB( 70,120, 60), RGB(170, 70, 40), RGB( 50,105, 40), RGB(150, 50, 25), RGB( 40,100,140), RGB(175,125, 25), RGB(110, 80,140), RGB(100, 80, 60), RGB(180,160,140), RGB(190,120, 90), RGB(120,160,110) },
// 29. Color-Safe (light): Okabe-Ito palette, readable with colour-vision deficiency
{ RGB( 0,114,178), RGB(213, 94, 0), RGB( 0, 90,150), RGB(190, 75, 0), RGB(204,121,167), RGB(205,135, 0), RGB( 0,158,115), RGB( 40, 40, 40), RGB(170,170,170), RGB(225,150,110), RGB( 86,180,233) },
// 30. Monochrome (light): minimal - green / red accents, charcoal TR, greys
{ RGB( 0,130, 80), RGB(190, 40, 40), RGB( 0,110, 65), RGB(165, 25, 25), RGB( 60, 60, 60), RGB(130,130,130), RGB( 90,110,150), RGB(120,100, 70), RGB(180,180,180), RGB(175,150,150), RGB(140,165,155) },
};
const int RG_THEME_COUNT = 30;
static_assert(sizeof(RG_THEMES) / sizeof(RG_THEMES[0]) == RG_THEME_COUNT,
"RG_THEMES must have one entry per theme name in RG_THEME_NAMES");
// Dropdown entries: the 30 themes in RG_THEMES order, then Custom.
static const char RG_THEME_NAMES[] =
"1. Classic Neon (dark);"
"2. Midnight Ocean (dark);"
"3. Emerald & Ruby (dark);"
"4. Solarized (dark);"
"5. Nord Aurora (dark);"
"6. Dracula (dark);"
"7. Monokai (dark);"
"8. Gruvbox (dark);"
"9. Tokyo Night (dark);"
"10. Catppuccin Mocha (dark);"
"11. Terminal Amber (dark);"
"12. Cyberpunk (dark);"
"13. Aurora Borealis (dark);"
"14. Sunset Boulevard (dark);"
"15. Steel & Copper (dark);"
"16. Forest Canopy (dark);"
"17. Royal Velvet (dark);"
"18. Graphite (dark);"
"19. Vaporwave (dark);"
"20. Tropical (dark);"
"21. Twilight Rose (dark);"
"22. Color-Safe (dark);"
"23. Paper Classic (light);"
"24. Solarized (light);"
"25. Salmon Paper (light);"
"26. Nordic (light);"
"27. Ink & Coral (light);"
"28. Earth Tones (light);"
"29. Color-Safe (light);"
"30. Monochrome (light);"
"Custom (Study Settings colors)";
// Mix two colours: t = 0 gives A, t = 1 gives B.
static COLORREF RG_Mix(COLORREF A, COLORREF B, float t)
{
if (t < 0.0f) t = 0.0f;
if (t > 1.0f) t = 1.0f;
const int ar = A & 0xFF, ag = (A >> 8) & 0xFF, ab = (A >> 16) & 0xFF;
const int br = B & 0xFF, bg = (B >> 8) & 0xFF, bb = (B >> 16) & 0xFF;
return RGB(static_cast<int>(ar + (br - ar) * t + 0.5f),
static_cast<int>(ag + (bg - ag) * t + 0.5f),
static_cast<int>(ab + (bb - ab) * t + 0.5f));
}
// Writes the selected theme into the subgraph colours (and the two Little Rizzy line colour
// inputs) that every module draws with. Custom: nothing is changed.
static void RG_ApplyTheme(SCStudyInterfaceRef sc)
{
const int index = sc.Input[RG_IN_THEME].GetIndex();
if (index < 0 || index >= RG_THEME_COUNT)
return;
const RG_Theme& T = RG_THEMES[index];
const COLORREF back = sc.ChartBackgroundColor;
const int brightness = ((back & 0xFF) * 299 + ((back >> 8) & 0xFF) * 587 + ((back >> 16) & 0xFF) * 114) / 1000;
const COLORREF contrast = (brightness < 128) ? RGB(255, 255, 255) : RGB(0, 0, 0);
auto Set = [&](int sg, COLORREF c)
{
sc.Subgraph[sg].PrimaryColor = c;
};
auto SetFill = [&](int sg, COLORREF c)
{
sc.Subgraph[sg].PrimaryColor = c;
sc.Subgraph[sg].SecondaryColor = c;
};
// ---- REVERSAL GRAIL
Set(0, T.Buy); // Buy
Set(1, T.Sell); // Sell
Set(2, T.BuyPlus); // Buy A+
Set(3, T.SellPlus); // Sell A+
Set(8, T.Target); // Target Hit (classic squares)
Set(13, T.Trampoline); // Trampoline Buy
Set(14, T.Trampoline); // Trampoline Sell
Set(15, RG_Mix(T.CloudLower, back, 0.72f)); // Engulfing Green BB (background)
Set(16, RG_Mix(T.CloudUpper, back, 0.72f)); // Engulfing Red BB (background)
Set(17, T.Squeeze); // Squeeze Buy Dot
Set(18, T.Squeeze); // Squeeze Sell Dot
SetFill(25, T.CloudUpper); // upper cloud fill
SetFill(26, T.CloudUpper);
SetFill(27, T.CloudLower); // lower cloud fill
SetFill(28, T.CloudLower);
Set(30, RG_Mix(T.CloudUpper, back, 0.35f)); // Upper Cloud Outer Line
Set(31, T.CloudUpper); // Upper Cloud Inner Line
Set(32, T.CloudLower); // Lower Cloud Inner Line
Set(33, RG_Mix(T.CloudLower, back, 0.35f)); // Lower Cloud Outer Line
// ---- LITTLE RIZZY
Set(RG_SG_LITTLE_RIZZY + 6, T.Target); // target line colour
Set(RG_SG_LITTLE_RIZZY + 7, RG_Mix(contrast, T.Target, 0.25f)); // touch blink colour
Set(RG_SG_LITTLE_RIZZY + 8, T.Expired); // invalidated-setup dots
sc.Input[RG_IN_RIZZY + 3].SetColor(RG_Mix(RGB(140, 140, 150), T.Target, 0.12f)); // broken lines
sc.Input[RG_IN_RIZZY + 4].SetColor(T.Expired); // expired lines
// ---- REVERSAL VOLUME PATTERNS
Set(RG_SG_VOLUME_PATTERN + 0, T.Volume);
Set(RG_SG_VOLUME_PATTERN + 1, T.Volume);
}
// =============================================================================================
// MODULE 1: REVERSAL GRAIL signal
// =============================================================================================
static void RG_SignalModule(SCStudyInterfaceRef sc, RG_ExternalAlerts& Ext)
{
// ---------------------------------------------------------------- subgraphs
SCSubgraphRef Subgraph_Buy = sc.Subgraph[0];
SCSubgraphRef Subgraph_Sell = sc.Subgraph[1];
SCSubgraphRef Subgraph_BuyAPlus = sc.Subgraph[2];
SCSubgraphRef Subgraph_SellAPlus = sc.Subgraph[3];
SCSubgraphRef Subgraph_Stop = sc.Subgraph[4];
SCSubgraphRef Subgraph_Target = sc.Subgraph[5];
SCSubgraphRef Subgraph_BullScore = sc.Subgraph[6];
SCSubgraphRef Subgraph_BearScore = sc.Subgraph[7];
SCSubgraphRef Subgraph_TargetHit = sc.Subgraph[8];
SCSubgraphRef Subgraph_OpenEqMark = sc.Subgraph[9];
SCSubgraphRef Subgraph_OpenEqBandMark = sc.Subgraph[10];
SCSubgraphRef Subgraph_BandUpper = sc.Subgraph[11];
SCSubgraphRef Subgraph_BandLower = sc.Subgraph[12];
SCSubgraphRef Subgraph_TrampBuy = sc.Subgraph[13];
SCSubgraphRef Subgraph_TrampSell = sc.Subgraph[14];
SCSubgraphRef Subgraph_EngulfBull = sc.Subgraph[15];
SCSubgraphRef Subgraph_EngulfBear = sc.Subgraph[16];
SCSubgraphRef Subgraph_SqueezeBuy = sc.Subgraph[17];
SCSubgraphRef Subgraph_SqueezeSell = sc.Subgraph[18];
// internal (unnamed, not drawn): outputs of the Sierra Chart functions TraderOracle uses
SCSubgraphRef Subgraph_PatRSI = sc.Subgraph[19];
SCSubgraphRef Subgraph_PatBB = sc.Subgraph[20];
SCSubgraphRef Subgraph_SqA = sc.Subgraph[21];
SCSubgraphRef Subgraph_SqD = sc.Subgraph[22];
SCSubgraphRef Subgraph_SqHist = sc.Subgraph[23];
SCFloatArrayRef Array_SqState = Subgraph_SqHist.Arrays[0]; // squeeze dot state after each bar
SCSubgraphRef Subgraph_Signal = sc.Subgraph[24];
// label bookkeeping (extra arrays of internal subgraphs)
SCFloatArrayRef Array_PatFlags = Subgraph_SqD.Arrays[0]; // 1 TR buy, 2 TR sell, 4 SQ buy, 8 SQ sell
SCFloatArrayRef Array_LabelMask = Subgraph_SqD.Arrays[1]; // labels currently drawn at each bar
SCFloatArrayRef Array_TPFlags = Subgraph_SqA.Arrays[0]; // 1 = a buy's target hit here, 2 = a sell's
SCFloatArrayRef Array_TPBuyValue = Subgraph_SqA.Arrays[1];
SCFloatArrayRef Array_TPSellValue = Subgraph_SqA.Arrays[2];
// internal per-bar state (extra arrays of in-use subgraphs)
SCFloatArrayRef Array_ATR = Subgraph_Buy.Arrays[0];
SCFloatArrayRef Array_EMA = Subgraph_Buy.Arrays[1];
SCFloatArrayRef Array_TDBull = Subgraph_Buy.Arrays[2];
SCFloatArrayRef Array_LastBuy = Subgraph_Buy.Arrays[3]; // index of most recent buy at or before bar
SCFloatArrayRef Array_BuyStop = Subgraph_Buy.Arrays[4];
SCFloatArrayRef Array_BuyTarget = Subgraph_Buy.Arrays[5];
SCFloatArrayRef Array_BuyFlags = Subgraph_Buy.Arrays[6]; // 1 = open = prior close, 2 = band break
SCFloatArrayRef Array_TDBear = Subgraph_Sell.Arrays[0];
SCFloatArrayRef Array_LastSell = Subgraph_Sell.Arrays[1];
SCFloatArrayRef Array_SellStop = Subgraph_Sell.Arrays[2];
SCFloatArrayRef Array_SellTarget = Subgraph_Sell.Arrays[3];
SCFloatArrayRef Array_SellFlags = Subgraph_Sell.Arrays[4];
// trade tracking, indexed by the signal bar
SCFloatArrayRef Array_BuyResBar = Subgraph_BuyAPlus.Arrays[0]; // bar where the trade resolved
SCFloatArrayRef Array_BuyResType = Subgraph_BuyAPlus.Arrays[1]; // 0 open, 1 target, -1 stop, 2 expired
SCFloatArrayRef Array_BuyTPAlerted = Subgraph_BuyAPlus.Arrays[2]; // target event already handled
SCFloatArrayRef Array_BuyTPLive = Subgraph_BuyAPlus.Arrays[3]; // target touched live first: bar index + 1
SCFloatArrayRef Array_SellResBar = Subgraph_SellAPlus.Arrays[0];
SCFloatArrayRef Array_SellResType = Subgraph_SellAPlus.Arrays[1];
SCFloatArrayRef Array_SellTPAlerted = Subgraph_SellAPlus.Arrays[2];
SCFloatArrayRef Array_SellTPLive = Subgraph_SellAPlus.Arrays[3];
SCFloatArrayRef Array_BandUpper = Subgraph_BandUpper.Arrays[0];
SCFloatArrayRef Array_BandLower = Subgraph_BandLower.Arrays[0];
// Resistance Cloud: each Fill Top subgraph is immediately followed by its Fill Bottom.
SCSubgraphRef Subgraph_CloudUpperOuter = sc.Subgraph[25]; // upper cloud, top edge (avg bound)
SCSubgraphRef Subgraph_CloudUpperInner = sc.Subgraph[26]; // upper cloud, bottom edge (near bound)
SCSubgraphRef Subgraph_CloudLowerInner = sc.Subgraph[27]; // lower cloud, top edge (near bound)
SCSubgraphRef Subgraph_CloudLowerOuter = sc.Subgraph[28]; // lower cloud, bottom edge (avg bound)
SCSubgraphRef Subgraph_WickInCloud = sc.Subgraph[29];
// Edge lines, so the cloud is visible even where a transparent fill is not drawn.
SCSubgraphRef Subgraph_CloudUpperOuterLine = sc.Subgraph[30];
SCSubgraphRef Subgraph_CloudUpperInnerLine = sc.Subgraph[31];
SCSubgraphRef Subgraph_CloudLowerInnerLine = sc.Subgraph[32];
SCSubgraphRef Subgraph_CloudLowerOuterLine = sc.Subgraph[33];
SCFloatArrayRef Array_CloudYC = Subgraph_CloudUpperOuter.Arrays[0]; // kernel average of close
SCFloatArrayRef Array_CloudYH = Subgraph_CloudUpperOuter.Arrays[1]; // ... of high
SCFloatArrayRef Array_CloudYL = Subgraph_CloudUpperOuter.Arrays[2]; // ... of low
SCFloatArrayRef Array_CloudATR = Subgraph_CloudUpperOuter.Arrays[3]; // Wilder ATR of the kernel series
SCFloatArrayRef Array_UpperNear = Subgraph_CloudUpperOuter.Arrays[4];
SCFloatArrayRef Array_LowerNear = Subgraph_CloudUpperOuter.Arrays[5];
SCFloatArrayRef Array_UpperAvg = Subgraph_CloudUpperOuter.Arrays[6];
SCFloatArrayRef Array_LowerAvg = Subgraph_CloudUpperOuter.Arrays[7];
SCFloatArrayRef Array_CloudFlags = Subgraph_CloudLowerOuter.Arrays[0]; // 1 = low in lower cloud, 2 = high in upper cloud
// ---------------------------------------------------------------- inputs
// Inputs are numbered without gaps: Sierra Chart stops listing inputs at the first unused number.
SCInputRef Input_MaxTrackBars = sc.Input[RG_IN_GRAIL + 0];
SCInputRef Input_AlertSignal = sc.Input[RG_IN_GRAIL + 1];
SCInputRef Input_AlertSignalSound = sc.Input[RG_IN_GRAIL + 2];
SCInputRef Input_AlertTarget = sc.Input[RG_IN_GRAIL + 3];
SCInputRef Input_AlertTargetSound = sc.Input[RG_IN_GRAIL + 4];
SCInputRef Input_AlertOpenEq = sc.Input[RG_IN_GRAIL + 5];
SCInputRef Input_AlertOpenEqSound = sc.Input[RG_IN_GRAIL + 6];
SCInputRef Input_AlertOpenEqBand = sc.Input[RG_IN_GRAIL + 7];
SCInputRef Input_AlertOpenEqBandSound= sc.Input[RG_IN_GRAIL + 8];
SCInputRef Input_ShowSqueeze = sc.Input[RG_IN_GRAIL + 9];
SCInputRef Input_SqueezeOffset = sc.Input[RG_IN_GRAIL + 10];
SCInputRef Input_TrampOffset = sc.Input[RG_IN_GRAIL + 11];
SCInputRef Input_AlertTramp = sc.Input[RG_IN_GRAIL + 12];
SCInputRef Input_AlertTrampSound = sc.Input[RG_IN_GRAIL + 13];
SCInputRef Input_AlertEngulf = sc.Input[RG_IN_GRAIL + 14];
SCInputRef Input_AlertEngulfSound = sc.Input[RG_IN_GRAIL + 15];
SCInputRef Input_AlertSqueeze = sc.Input[RG_IN_GRAIL + 16];
SCInputRef Input_AlertSqueezeSound = sc.Input[RG_IN_GRAIL + 17];
SCInputRef Input_ShowCloud = sc.Input[RG_IN_GRAIL + 18];
SCInputRef Input_CloudTransparency = sc.Input[RG_IN_GRAIL + 19];
SCInputRef Input_TagText = sc.Input[RG_IN_GRAIL + 20];
SCInputRef Input_PinStem = sc.Input[RG_IN_GRAIL + 21];
SCInputRef Input_PinStemLength = sc.Input[RG_IN_GRAIL + 22];
SCInputRef Input_AlertWickCloud = sc.Input[RG_IN_GRAIL + 23];
SCInputRef Input_AlertWickCloudSound = sc.Input[RG_IN_GRAIL + 24];
SCInputRef Input_AlertSqCloud = sc.Input[RG_IN_GRAIL + 25];
SCInputRef Input_AlertSqCloudSound = sc.Input[RG_IN_GRAIL + 26];
SCInputRef Input_AlertTrCloud = sc.Input[RG_IN_GRAIL + 27];
SCInputRef Input_AlertTrCloudSound = sc.Input[RG_IN_GRAIL + 28];
SCInputRef Input_Alert4Band = sc.Input[RG_IN_GRAIL + 29];
if (sc.SetDefaults)
{
sc.GraphName = "TO Method v4";
sc.StudyDescription =
"Reversal signal at a fresh N-bar extreme, scored 0-4 on persistence (TD-style count), "
"%B momentum divergence, quiet volume and 200-EMA trend side, with vetoes for band "
"blow-throughs, wide-range bars and climax volume. Non-repainting on bar close. "
"Alerts for new arrows, targets hit before the stop, signal bars that open at the prior "
"close, and those that also broke the outer Bollinger band. Also shows the TraderOracle "
"trampoline, engulfing-at-band and squeeze dot patterns and the TraderOracle Method "
"Resistance Cloud (Nadaraya-Watson envelope), with their own alerts. Includes the Little "
"Rizzy measured-move levels and the Reversal Volume Patterns. 30 colour themes.";
sc.AutoLoop = 0;
sc.GraphRegion = 0;
sc.ValueFormat = VALUEFORMAT_INHERITED;
sc.AlertOnlyOncePerBar = 0;
sc.ResetAlertOnNewBar = 1;
// Colours below are the defaults (theme 1, Classic Neon); the colour theme replaces them.
Subgraph_Buy.Name = "Buy";
Subgraph_Buy.DrawStyle = DRAWSTYLE_ARROW_UP;
Subgraph_Buy.PrimaryColor = RGB(0, 230, 255);
Subgraph_Buy.LineWidth = 3;
Subgraph_Buy.DrawZeros = false;
Subgraph_Sell.Name = "Sell";
Subgraph_Sell.DrawStyle = DRAWSTYLE_ARROW_DOWN;
Subgraph_Sell.PrimaryColor = RGB(255, 60, 170);
Subgraph_Sell.LineWidth = 3;
Subgraph_Sell.DrawZeros = false;
Subgraph_BuyAPlus.Name = "Buy A+ (score 4)";
Subgraph_BuyAPlus.DrawStyle = DRAWSTYLE_ARROW_UP;
Subgraph_BuyAPlus.PrimaryColor = RGB(0, 230, 255);
Subgraph_BuyAPlus.LineWidth = 6;
Subgraph_BuyAPlus.DrawZeros = false;
Subgraph_SellAPlus.Name = "Sell A+ (score 4)";
Subgraph_SellAPlus.DrawStyle = DRAWSTYLE_ARROW_DOWN;
Subgraph_SellAPlus.PrimaryColor = RGB(255, 60, 170);
Subgraph_SellAPlus.LineWidth = 6;
Subgraph_SellAPlus.DrawZeros = false;
Subgraph_Stop.Name = "Stop";
Subgraph_Stop.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_Stop.PrimaryColor = RGB(200, 80, 80);
Subgraph_Stop.LineWidth = 2;
Subgraph_Stop.DrawZeros = false;
Subgraph_Target.Name = "Target";
Subgraph_Target.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_Target.PrimaryColor = RGB(80, 160, 255);
Subgraph_Target.LineWidth = 2;
Subgraph_Target.DrawZeros = false;
Subgraph_BullScore.Name = "Bull Score";
Subgraph_BullScore.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_BullScore.PrimaryColor = RGB(0, 200, 120);
Subgraph_BullScore.DrawZeros = false;
Subgraph_BearScore.Name = "Bear Score";
Subgraph_BearScore.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_BearScore.PrimaryColor = RGB(230, 60, 60);
Subgraph_BearScore.DrawZeros = false;
Subgraph_TargetHit.Name = "Target Hit";
Subgraph_TargetHit.DrawStyle = DRAWSTYLE_SQUARE;
Subgraph_TargetHit.PrimaryColor = RGB(252, 236, 188);
Subgraph_TargetHit.LineWidth = 4;
Subgraph_TargetHit.DrawZeros = false;
Subgraph_OpenEqMark.Name = "Open = Prior Close";
Subgraph_OpenEqMark.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_OpenEqMark.PrimaryColor = RGB(120, 170, 255);
Subgraph_OpenEqMark.LineWidth = 4;
Subgraph_OpenEqMark.DrawZeros = false;
Subgraph_OpenEqBandMark.Name = "Open = Prior Close + Band Break";
Subgraph_OpenEqBandMark.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_OpenEqBandMark.PrimaryColor = RGB(255, 140, 0);
Subgraph_OpenEqBandMark.LineWidth = 6;
Subgraph_OpenEqBandMark.DrawZeros = false;
Subgraph_BandUpper.Name = "Alert Band Upper";
Subgraph_BandUpper.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_BandUpper.PrimaryColor = RGB(130, 130, 160);
Subgraph_BandUpper.LineWidth = 1;
Subgraph_BandUpper.DrawZeros = false;
Subgraph_BandLower.Name = "Alert Band Lower";
Subgraph_BandLower.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_BandLower.PrimaryColor = RGB(130, 130, 160);
Subgraph_BandLower.LineWidth = 1;
Subgraph_BandLower.DrawZeros = false;
// ------------------------------------------------ signal inputs
Input_MaxTrackBars.Name = "Max Bars To Track Stop/Target";
Input_MaxTrackBars.SetInt(30);
Input_MaxTrackBars.SetIntLimits(1, 2000);
Input_MaxTrackBars.SetDescription("A signal's stop and target are watched for this many bars; after that the trade is treated as expired and no target alert is given.");
// ------------------------------------------------ alert inputs
const char* DIRECTIONS = "Off;Buys only;Sells only;Buys and sells";
Input_AlertSignal.Name = "Alert 1: Signal Arrow Appears";
Input_AlertSignal.SetCustomInputStrings(DIRECTIONS);
Input_AlertSignal.SetCustomInputIndex(3);
Input_AlertSignalSound.Name = "Alert 1: Sound Number (0 = log only)";
Input_AlertSignalSound.SetInt(1);
Input_AlertSignalSound.SetIntLimits(0, 150);
Input_AlertTarget.Name = "Alert 2: Target Hit Before Stop";
Input_AlertTarget.SetCustomInputStrings(DIRECTIONS);
Input_AlertTarget.SetCustomInputIndex(3);
Input_AlertTargetSound.Name = "Alert 2: Sound Number (0 = log only)";
Input_AlertTargetSound.SetInt(2);
Input_AlertTargetSound.SetIntLimits(0, 150);
Input_AlertOpenEq.Name = "Alert 3: Signal Bar Open = Prior Close";
Input_AlertOpenEq.SetCustomInputStrings(DIRECTIONS);
Input_AlertOpenEq.SetCustomInputIndex(3);
Input_AlertOpenEqSound.Name = "Alert 3: Sound Number (0 = log only)";
Input_AlertOpenEqSound.SetInt(3);
Input_AlertOpenEqSound.SetIntLimits(0, 150);
Input_AlertOpenEqBand.Name = "Alert 4: Open = Prior Close + Band Break";
Input_AlertOpenEqBand.SetCustomInputStrings(DIRECTIONS);
Input_AlertOpenEqBand.SetCustomInputIndex(3);
Input_AlertOpenEqBandSound.Name = "Alert 4: Sound Number (0 = log only)";
Input_AlertOpenEqBandSound.SetInt(4);
Input_AlertOpenEqBandSound.SetIntLimits(0, 150);
// ------------------------------------------------ TraderOracle patterns
Subgraph_TrampBuy.Name = "Trampoline Buy";
Subgraph_TrampBuy.DrawStyle = DRAWSTYLE_TRIANGLE_UP;
Subgraph_TrampBuy.PrimaryColor = RGB(230, 30, 30);
Subgraph_TrampBuy.LineWidth = 3;
Subgraph_TrampBuy.DrawZeros = false;
Subgraph_TrampSell.Name = "Trampoline Sell";
Subgraph_TrampSell.DrawStyle = DRAWSTYLE_TRIANGLE_DOWN;
Subgraph_TrampSell.PrimaryColor = RGB(230, 30, 30);
Subgraph_TrampSell.LineWidth = 3;
Subgraph_TrampSell.DrawZeros = false;
Subgraph_EngulfBull.Name = "Engulfing Green BB";
Subgraph_EngulfBull.DrawStyle = DRAWSTYLE_BACKGROUND;
Subgraph_EngulfBull.PrimaryColor = RGB(0, 64, 0);
Subgraph_EngulfBull.LineWidth = 1;
Subgraph_EngulfBull.DrawZeros = false;
Subgraph_EngulfBear.Name = "Engulfing Red BB";
Subgraph_EngulfBear.DrawStyle = DRAWSTYLE_BACKGROUND;
Subgraph_EngulfBear.PrimaryColor = RGB(70, 0, 35);
Subgraph_EngulfBear.LineWidth = 1;
Subgraph_EngulfBear.DrawZeros = false;
Subgraph_SqueezeBuy.Name = "Squeeze Buy Dot";
Subgraph_SqueezeBuy.DrawStyle = DRAWSTYLE_STAR;
Subgraph_SqueezeBuy.PrimaryColor = RGB(255, 196, 0);
Subgraph_SqueezeBuy.LineWidth = 1;
Subgraph_SqueezeBuy.DrawZeros = false;
Subgraph_SqueezeSell.Name = "Squeeze Sell Dot";
Subgraph_SqueezeSell.DrawStyle = DRAWSTYLE_STAR;
Subgraph_SqueezeSell.PrimaryColor = RGB(255, 196, 0);
Subgraph_SqueezeSell.LineWidth = 1;
Subgraph_SqueezeSell.DrawZeros = false;
Input_ShowSqueeze.Name = "Show Squeeze Dots";
Input_ShowSqueeze.SetYesNo(0);
Input_SqueezeOffset.Name = "Squeeze Dot Offset (ticks)";
Input_SqueezeOffset.SetInt(2);
Input_SqueezeOffset.SetIntLimits(0, 1000);
Input_TrampOffset.Name = "Trampoline Marker Offset (ticks)";
Input_TrampOffset.SetInt(6);
Input_TrampOffset.SetIntLimits(0, 1000);
Input_AlertTramp.Name = "Alert 5: Trampoline";
Input_AlertTramp.SetCustomInputStrings(DIRECTIONS);
Input_AlertTramp.SetCustomInputIndex(0);
Input_AlertTrampSound.Name = "Alert 5: Sound Number (0 = log only)";
Input_AlertTrampSound.SetInt(5);
Input_AlertTrampSound.SetIntLimits(0, 150);
Input_AlertEngulf.Name = "Alert 6: Engulfing At Band";
Input_AlertEngulf.SetCustomInputStrings(DIRECTIONS);
Input_AlertEngulf.SetCustomInputIndex(0);
Input_AlertEngulfSound.Name = "Alert 6: Sound Number (0 = log only)";
Input_AlertEngulfSound.SetInt(6);
Input_AlertEngulfSound.SetIntLimits(0, 150);
Input_AlertSqueeze.Name = "Alert 7: Squeeze Dot";
Input_AlertSqueeze.SetCustomInputStrings(DIRECTIONS);
Input_AlertSqueeze.SetCustomInputIndex(0);
Input_AlertSqueezeSound.Name = "Alert 7: Sound Number (0 = log only)";
Input_AlertSqueezeSound.SetInt(7);
Input_AlertSqueezeSound.SetIntLimits(0, 150);
// ------------------------------------------------ marker style
Subgraph_PatRSI.Name = "(internal) Pattern RSI";
Subgraph_PatRSI.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_PatBB.Name = "(internal) Pattern Bollinger";
Subgraph_PatBB.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_SqA.Name = "(internal) Squeeze Average";
Subgraph_SqA.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_SqD.Name = "(internal) Squeeze Delta";
Subgraph_SqD.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_SqHist.Name = "(internal) Squeeze Histogram";
Subgraph_SqHist.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_Signal.Name = "Signal";
Subgraph_Signal.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_Signal.PrimaryColor = RGB(160, 160, 160);
Subgraph_Signal.DrawZeros = false;
Input_TagText.Name = "Signal Tag Text";
Input_TagText.SetCustomInputStrings("BUY / SELL (A+ = BUY+ / SELL+);LONG / SHORT (A+ = LONG+ / SHORT+)");
Input_TagText.SetCustomInputIndex(0);
Input_PinStem.Name = "Pin Stem Under Signal Tags";
Input_PinStem.SetYesNo(0);
Input_PinStem.SetDescription("Hang each tag on a thin stem, further from the bar.");
Input_PinStemLength.Name = "Pin Stem Length (x ATR)";
Input_PinStemLength.SetFloat(1.0f);
Input_PinStemLength.SetFloatLimits(0.1f, 20.0f);
// ------------------------------------------------ Resistance Cloud
Subgraph_CloudUpperOuter.Name = "Upper Cloud Outer Edge";
Subgraph_CloudUpperOuter.DrawStyle = DRAWSTYLE_TRANSPARENT_FILL_TOP;
Subgraph_CloudUpperOuter.PrimaryColor = RGB(224, 49, 73);
Subgraph_CloudUpperOuter.DrawZeros = false;
Subgraph_CloudUpperInner.Name = "Upper Cloud Inner Edge";
Subgraph_CloudUpperInner.DrawStyle = DRAWSTYLE_TRANSPARENT_FILL_BOTTOM;
Subgraph_CloudUpperInner.PrimaryColor = RGB(224, 49, 73);
Subgraph_CloudUpperInner.DrawZeros = false;
Subgraph_CloudLowerInner.Name = "Lower Cloud Inner Edge";
Subgraph_CloudLowerInner.DrawStyle = DRAWSTYLE_TRANSPARENT_FILL_TOP;
Subgraph_CloudLowerInner.PrimaryColor = RGB(0, 168, 107);
Subgraph_CloudLowerInner.DrawZeros = false;
Subgraph_CloudLowerOuter.Name = "Lower Cloud Outer Edge";
Subgraph_CloudLowerOuter.DrawStyle = DRAWSTYLE_TRANSPARENT_FILL_BOTTOM;
Subgraph_CloudLowerOuter.PrimaryColor = RGB(0, 168, 107);
Subgraph_CloudLowerOuter.DrawZeros = false;
Subgraph_CloudUpperOuterLine.Name = "Upper Cloud Outer Line";
Subgraph_CloudUpperOuterLine.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_CloudUpperOuterLine.PrimaryColor = RGB(150, 40, 60);
Subgraph_CloudUpperOuterLine.LineWidth = 1;
Subgraph_CloudUpperOuterLine.DrawZeros = false;
Subgraph_CloudUpperInnerLine.Name = "Upper Cloud Inner Line";
Subgraph_CloudUpperInnerLine.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_CloudUpperInnerLine.PrimaryColor = RGB(224, 49, 73);
Subgraph_CloudUpperInnerLine.LineWidth = 2;
Subgraph_CloudUpperInnerLine.DrawZeros = false;
Subgraph_CloudLowerInnerLine.Name = "Lower Cloud Inner Line";
Subgraph_CloudLowerInnerLine.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_CloudLowerInnerLine.PrimaryColor = RGB(0, 168, 107);
Subgraph_CloudLowerInnerLine.LineWidth = 2;
Subgraph_CloudLowerInnerLine.DrawZeros = false;
Subgraph_CloudLowerOuterLine.Name = "Lower Cloud Outer Line";
Subgraph_CloudLowerOuterLine.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_CloudLowerOuterLine.PrimaryColor = RGB(0, 110, 72);
Subgraph_CloudLowerOuterLine.LineWidth = 1;
Subgraph_CloudLowerOuterLine.DrawZeros = false;
Subgraph_WickInCloud.Name = "Large Wick In Cloud";
Subgraph_WickInCloud.DrawStyle = DRAWSTYLE_IGNORE;
Subgraph_WickInCloud.PrimaryColor = RGB(255, 196, 0);
Subgraph_WickInCloud.LineWidth = 3;
Subgraph_WickInCloud.DrawZeros = false;
Input_ShowCloud.Name = "Show Resistance Cloud";
Input_ShowCloud.SetYesNo(1);
Input_CloudTransparency.Name = "Cloud Transparency %";
Input_CloudTransparency.SetInt(78);
Input_CloudTransparency.SetIntLimits(0, 100);
Input_CloudTransparency.SetDescription("Applied to the study's Transparency Level (used only by the cloud fill).");
Input_AlertWickCloud.Name = "Alert 8: Large Wick In Cloud";
Input_AlertWickCloud.SetCustomInputStrings(DIRECTIONS);
Input_AlertWickCloud.SetCustomInputIndex(0);
Input_AlertWickCloudSound.Name = "Alert 8: Sound Number (0 = log only)";
Input_AlertWickCloudSound.SetInt(8);
Input_AlertWickCloudSound.SetIntLimits(0, 150);
Input_AlertSqCloud.Name = "Alert 9: Squeeze Dot In Cloud";
Input_AlertSqCloud.SetCustomInputStrings(DIRECTIONS);
Input_AlertSqCloud.SetCustomInputIndex(0);
Input_AlertSqCloudSound.Name = "Alert 9: Sound Number (0 = log only)";
Input_AlertSqCloudSound.SetInt(9);
Input_AlertSqCloudSound.SetIntLimits(0, 150);
Input_AlertTrCloud.Name = "Alert 10: Trampoline In Cloud";
Input_AlertTrCloud.SetCustomInputStrings(DIRECTIONS);
Input_AlertTrCloud.SetCustomInputIndex(0);
Input_AlertTrCloudSound.Name = "Alert 10: Sound Number (0 = log only)";
Input_AlertTrCloudSound.SetInt(10);
Input_AlertTrCloudSound.SetIntLimits(0, 150);
Input_Alert4Band.Name = "Alert 4 Band";
Input_Alert4Band.SetCustomInputStrings("Alert Bollinger Bands;Resistance Cloud inner edge");
Input_Alert4Band.SetCustomInputIndex(0);
return;
}
// ---------------------------------------------------------------- settings
const int lookback = TOMethod4::EXTREME_LOOKBACK_BARS;
const int minScore = TOMethod4::MIN_SCORE_TO_SIGNAL;
const int tdMin = TOMethod4::PERSISTENCE_COUNT;
const int divFar = UrsMaxI(TOMethod4::DIVERGENCE_WINDOW_START, TOMethod4::DIVERGENCE_WINDOW_END + 1);
const int divNear = TOMethod4::DIVERGENCE_WINDOW_END;
const int bbLen = TOMethod4::ZSCORE_BOLLINGER_LENGTH;
const bool useVol = TOMethod4::USE_VOLUME;