1313
1414namespace Dashboard . Pages . Futures
1515{
16+ public class Indexer : List < ( long , double ) >
17+ {
18+ public new void Add ( ( long , double ) item )
19+ {
20+ if ( Count is 0 || item . Item1 > this [ ^ 1 ] . Item1 )
21+ {
22+ base . Add ( item ) ;
23+ }
24+
25+ this [ ^ 1 ] = item ;
26+ }
27+ }
28+
1629 public partial class Covariance
1730 {
1831 ControlsComponent View { get ; set ; }
@@ -27,13 +40,18 @@ public partial class Covariance
2740 PerformanceIndicator Performance { get ; set ; }
2841 Dictionary < string , ScaleIndicator > Scales { get ; set ; }
2942
43+ int Direction { get ; set ; } = 0 ;
3044 double Deviation { get ; set ; } = 2 ;
45+ Indexer Scores { get ; set ; } = new ( ) ;
3146 AverageService AverageService { get ; set ; } = new ( ) ;
3247
48+ const string nameX = "ESU25" ;
49+ const string nameY = "NQU25" ;
50+
3351 Dictionary < string , Instrument > Instruments = new ( )
3452 {
35- [ "ESU25" ] = new ( ) { Name = "ESU25" , StepValue = 12.50 , StepSize = 0.25 , Leverage = 50 , Commission = 3.65 , TimeFrame = TimeSpan . FromSeconds ( 1 ) } ,
36- [ "NQU25" ] = new ( ) { Name = "NQU25" , StepValue = 5 , StepSize = 0.25 , Leverage = 20 , Commission = 3.65 , TimeFrame = TimeSpan . FromSeconds ( 1 ) } ,
53+ [ nameX ] = new ( ) { Name = nameX , StepValue = 12.50 , StepSize = 0.25 , Leverage = 50 , Commission = 3.65 } ,
54+ [ nameY ] = new ( ) { Name = nameY , StepValue = 5 , StepSize = 0.25 , Leverage = 20 , Commission = 3.65 } ,
3755 } ;
3856
3957 protected override async Task OnView ( )
@@ -74,16 +92,16 @@ protected override Task OnTrade()
7492 return base . OnTrade ( ) ;
7593 }
7694
77- protected override async void OnViewUpdate ( Instrument instrument )
95+ protected override async Task OnViewUpdate ( Instrument instrument )
7896 {
7997 var adapter = Adapter ;
8098 var account = adapter . Account ;
8199 var price = instrument . Price ;
82100 var index = price . Bar . Time . Value ;
83- var assetX = account . Instruments [ "ESU25" ] ;
84- var assetY = account . Instruments [ "NQU25" ] ;
85- var seriesX = ( await adapter . GetPriceGroups ( new Criteria { Count = 100 , Instrument = assetX } ) ) . Data ;
86- var seriesY = ( await adapter . GetPriceGroups ( new Criteria { Count = 100 , Instrument = assetY } ) ) . Data ;
101+ var assetX = account . Instruments [ nameX ] ;
102+ var assetY = account . Instruments [ nameY ] ;
103+ var seriesX = ( await adapter . GetPrices ( new ( ) { Count = 100 , Instrument = assetX } ) ) . Data ;
104+ var seriesY = ( await adapter . GetPrices ( new ( ) { Count = 100 , Instrument = assetY } ) ) . Data ;
87105
88106 if ( seriesX . Count is 0 || seriesY . Count is 0 )
89107 {
@@ -113,18 +131,18 @@ protected override async void OnViewUpdate(Instrument instrument)
113131
114132 protected override async Task OnTradeUpdate ( Instrument instrument )
115133 {
116- if ( Equals ( instrument . Name , "ESU25" ) is false )
134+ if ( Equals ( instrument . Name , nameX ) is false )
117135 {
118136 return ;
119137 }
120138
121139 var price = instrument . Price ;
122140 var adapter = Adapter ;
123141 var account = adapter . Account ;
124- var assetX = account . Instruments [ "ESU25" ] ;
125- var assetY = account . Instruments [ "NQU25" ] ;
126- var seriesX = ( await adapter . GetPrices ( new Criteria { Count = 100 , Instrument = assetX } ) ) . Data ;
127- var seriesY = ( await adapter . GetPrices ( new Criteria { Count = 100 , Instrument = assetY } ) ) . Data ;
142+ var assetX = account . Instruments [ nameX ] ;
143+ var assetY = account . Instruments [ nameY ] ;
144+ var seriesX = ( await adapter . GetPrices ( new ( ) { Count = 100 , Instrument = assetX } ) ) . Data ;
145+ var seriesY = ( await adapter . GetPrices ( new ( ) { Count = 100 , Instrument = assetY } ) ) . Data ;
128146
129147 if ( seriesX . Count is 0 || seriesY . Count is 0 )
130148 {
@@ -142,30 +160,24 @@ protected override async Task OnTradeUpdate(Instrument instrument)
142160 var retSeriesY = seriesY . Select ( o => o . Last . Value * assetY . Leverage . Value ) . ToArray ( ) ;
143161 var beta = CalculateHedgeRatio ( retSeriesX , retSeriesY ) ;
144162 var score = CalculateZScore ( retSeriesX , retSeriesY , beta , ( priceX . Last * assetX . Leverage . Value - beta * priceY . Last * assetY . Leverage . Value ) . Value ) ;
145- var isLong = score < - Deviation ;
146- var isShort = score > Deviation ;
147163
148- if ( Equals ( price . Bar . Time , scores . LastOrDefault ( ) . Item1 ) )
149- {
150- scores [ scores . Count - 1 ] = ( price . Bar . Time . Value , score ) ;
151- }
152- else
153- {
154- scores . Add ( ( price . Bar . Time . Value , score ) ) ;
155- }
164+ Scores . Add ( ( price . Bar . Time . Value , score ) ) ;
156165
157- var prevScore = scores . ElementAtOrDefault ( scores . Count - 2 ) . Item2 ;
166+ var isLong = score < - Deviation ;
167+ var isShort = score > Deviation ;
158168
159169 if ( positions . Count is 0 )
160170 {
161171 switch ( true )
162172 {
163173 case true when isLong :
174+ Direction = 1 ;
164175 await OpenPosition ( adapter , assetX , OrderSideEnum . Long ) ;
165176 await OpenPosition ( adapter , assetY , OrderSideEnum . Short ) ;
166177 break ;
167178
168179 case true when isShort :
180+ Direction = - 1 ;
169181 await OpenPosition ( adapter , assetX , OrderSideEnum . Short ) ;
170182 await OpenPosition ( adapter , assetY , OrderSideEnum . Long ) ;
171183 break ;
@@ -174,9 +186,9 @@ protected override async Task OnTradeUpdate(Instrument instrument)
174186
175187 if ( positions . Count is not 0 )
176188 {
177- var pos = positions . First ( ) ;
178- var closeLong = pos . Side is OrderSideEnum . Long && prevScore > 0 ;
179- var closeShort = pos . Side is OrderSideEnum . Short && prevScore < 0 ;
189+ var prevScore = Scores . ElementAtOrDefault ( Scores . Count - 1 ) . Item2 ;
190+ var closeLong = Direction is 1 && prevScore > 0 ;
191+ var closeShort = Direction is - 1 && prevScore < 0 ;
180192
181193 if ( closeLong || closeShort )
182194 {
@@ -186,8 +198,6 @@ protected override async Task OnTradeUpdate(Instrument instrument)
186198 }
187199 }
188200
189- List < ( long , double ) > scores = new ( ) ;
190-
191201 /// <summary>
192202 /// Calculates the Hedge Ratio (Beta) between two time series (Y vs X) using simple linear regression.
193203 /// This should be calculated over a long look-back window (e.g., 252 daily bars).
0 commit comments