@@ -20,85 +20,4 @@ function trade(overrides = {}) {
2020 entry_fill : 100 ,
2121 entry_atr : 10 ,
2222 initial_stop : 90 ,
23- exit_timestamp : 3 * FIVE ,
24- raw_exit_reference : 100 ,
25- exit_fill : 99.95 ,
26- exit_reason : "trend_exit" ,
27- quantity : 0.01 ,
28- entry_fee : 0.001 ,
29- exit_fee : 0.0009995 ,
30- gross_pnl : - 0.0005 ,
31- net_pnl : - 0.0024995 ,
32- net_return : - 0.0024995 ,
33- bars_held : 0 ,
34- ...overrides
35- } ;
36- }
37-
38- function candle ( timestamp : number , overrides = { } ) {
39- return {
40- timestamp,
41- open : 100 ,
42- high : 102 ,
43- low : 98 ,
44- close : 100 ,
45- volume : 1 ,
46- ...overrides
47- } ;
48- }
49-
50- function map ( candles : ReturnType < typeof candle > [ ] ) {
51- return new Map ( candles . map ( ( item ) => [ item . timestamp , item ] ) ) ;
52- }
53-
54- describe ( "Regime Trend v1 target-triggered ratchet" , ( ) => {
55- it ( "freezes exactly five candidates" , ( ) => {
56- expect ( TARGET_TRIGGERED_RATCHET_CANDIDATES ) . toHaveLength ( 5 ) ;
57- } ) ;
58-
59- it ( "activates after target touch and applies the floor only on the next 5m candle" , ( ) => {
60- const candidate = TARGET_TRIGGERED_RATCHET_CANDIDATES . find ( ( item ) => item . id === "touch-1.50-lock-0.00" ) ! ;
61- const candles = map ( [
62- candle ( 0 , { high : 116 , low : 95 } ) ,
63- candle ( FIVE , { open : 101 , high : 102 , low : 99 } ) ,
64- candle ( 2 * FIVE )
65- ] ) ;
66- const result = applyTargetTriggeredRatchet ( trade ( ) , [ ] , candles , candidate ) ;
67- expect ( result . activated ) . toBe ( true ) ;
68- expect ( result . classification ) . toBe ( "RATCHET_EXIT" ) ;
69- expect ( result . timestamp ) . toBe ( FIVE ) ;
70- } ) ;
71-
72- it ( "does not retroactively apply a ratchet inside the activation candle" , ( ) => {
73- const candidate = TARGET_TRIGGERED_RATCHET_CANDIDATES [ 0 ] ;
74- const candles = map ( [
75- candle ( 0 , { high : 116 , low : 89 } )
76- ] ) ;
77- const result = applyTargetTriggeredRatchet (
78- trade ( { exit_timestamp : FIVE , exit_reason : "initial_stop" } ) ,
79- [ ] ,
80- candles ,
81- candidate
82- ) ;
83- expect ( result . classification ) . toBe ( "BASELINE_STOP" ) ;
84- expect ( result . activated ) . toBe ( false ) ;
85- } ) ;
86-
87- it ( "keeps the baseline trend exit when activated but the floor is not touched" , ( ) => {
88- const candidate = TARGET_TRIGGERED_RATCHET_CANDIDATES [ 2 ] ;
89- const candles = map ( [
90- candle ( 0 , { high : 121 , low : 95 } ) ,
91- candle ( FIVE , { high : 125 , low : 101 } ) ,
92- candle ( 2 * FIVE , { high : 130 , low : 102 } )
93- ] ) ;
94- const result = applyTargetTriggeredRatchet ( trade ( ) , [ ] , candles , candidate ) ;
95- expect ( result . classification ) . toBe ( "ACTIVATED_BASELINE_EXIT" ) ;
96- expect ( result . trade . net_pnl ) . toBe ( trade ( ) . net_pnl ) ;
97- } ) ;
98-
99- it ( "returns DATA_GAP instead of inventing a missing 5m candle" , ( ) => {
100- const candidate = TARGET_TRIGGERED_RATCHET_CANDIDATES [ 0 ] ;
101- const result = applyTargetTriggeredRatchet ( trade ( ) , [ ] , map ( [ candle ( 0 ) ] ) , candidate ) ;
102- expect ( result . classification ) . toBe ( "DATA_GAP" ) ;
103- } ) ;
104- } ) ;
23+ exit_timestamp : 3
0 commit comments