@@ -17,27 +17,28 @@ namespace Dashboard.Pages.Options
1717{
1818 public partial class BreakProtection
1919 {
20+ static double IV { get ; set ; } = 0.15 ;
21+ static double DivRate { get ; set ; } = 0.05 ;
22+ static double RiskRate { get ; set ; } = 0.05 ;
23+ double ? Strike { get ; set ; }
24+ double ? StrikeUp { get ; set ; }
25+ double ? StrikeDown { get ; set ; }
26+ OptionSideEnum ? Side { get ; set ; }
27+
2028 ControlsComponent View { get ; set ; }
2129 ChartsComponent DataView { get ; set ; }
22- ChartsComponent DeltaView { get ; set ; }
23- ChartsComponent VarianceView { get ; set ; }
2430 ChartsComponent PerformanceView { get ; set ; }
2531 TransactionsComponent TransactionsView { get ; set ; }
2632 OrdersComponent OrdersView { get ; set ; }
2733 PositionsComponent PositionsView { get ; set ; }
2834 StatementsComponent StatementsView { get ; set ; }
2935 PerformanceIndicator Performance { get ; set ; }
30- OptionPriceService PriceService { get ; set ; } = new ( 0.05 , 0.05 , 0.15 ) ;
36+ OptionPriceService PriceService { get ; set ; } = new ( RiskRate , DivRate , IV ) ;
3137 Dictionary < string , Instrument > Instruments => new ( )
3238 {
3339 [ "SPY" ] = new Instrument { Name = "SPY" , TimeFrame = TimeSpan . FromMinutes ( 1 ) }
3440 } ;
3541
36- double ? Strike { get ; set ; }
37- double ? StrikeUp { get ; set ; }
38- double ? StrikeDown { get ; set ; }
39- OptionSideEnum ? Side { get ; set ; }
40-
4142 DateTime CurDate ( Price point )
4243 {
4344 var date = new DateTime ( point . Time . Value ) ;
@@ -72,13 +73,9 @@ IList<Order> Positions(IList<Order> positions, DateTime? date) => [.. positions
7273 protected override async Task OnView ( )
7374 {
7475 await DataView . Create ( "Data" ) ;
75- await DeltaView . Create ( "Delta" ) ;
76- await VarianceView . Create ( "Variance" ) ;
7776 await PerformanceView . Create ( "Performance" ) ;
7877
7978 DataView . Composers . ForEach ( o => o . ShowIndex = i => GetDate ( o . Items , ( int ) i ) ) ;
80- DeltaView . Composers . ForEach ( o => o . ShowIndex = i => GetDate ( o . Items , ( int ) i ) ) ;
81- VarianceView . Composers . ForEach ( o => o . ShowIndex = i => GetDate ( o . Items , ( int ) i ) ) ;
8279 PerformanceView . Composers . ForEach ( o => o . ShowIndex = i => GetDate ( o . Items , ( int ) i ) ) ;
8380 }
8481
@@ -88,7 +85,7 @@ protected override Task OnTrade()
8885 Adapter = new SimGateway
8986 {
9087 Connector = Connector ,
91- Source = "D:/Code/Options" , // Configuration["Documents:Resources"],
88+ Source = Configuration [ "Documents:Resources" ] ,
9289 Account = new ( )
9390 {
9491 Descriptor = "Demo" ,
@@ -107,17 +104,13 @@ protected override async void OnViewUpdate(Instrument instrument)
107104 var account = adapter . Account ;
108105 var positions = ( await adapter . GetPositions ( default ) ) . Data ;
109106 var performance = await Performance . Update ( Adapters . Values ) ;
110- var ( curDelta , nextDelta , sigma ) = GetIndicators ( positions , price ) ;
111107
112108 OrdersView . Update ( Adapters . Values ) ;
113109 PositionsView . Update ( Adapters . Values ) ;
114110 TransactionsView . Update ( Adapters . Values ) ;
115111 DataView . Update ( price . Bar . Time . Value , "Data" , "Bars" , DataView . GetShape < CandleShape > ( price ) ) ;
116112 PerformanceView . Update ( price . Time . Value , "Performance" , "Balance" , new AreaShape { Y = account . Balance + account . Performance } ) ;
117113 PerformanceView . Update ( price . Time . Value , "Performance" , "PnL" , PerformanceView . GetShape < LineShape > ( performance . Response , SKColors . OrangeRed ) ) ;
118- DeltaView . Update ( price . Time . Value , "Delta" , "Next Delta" , new BarShape { Y = nextDelta , Component = ComUp } ) ;
119- DeltaView . Update ( price . Time . Value , "Delta" , "Current Delta" , new LineShape { Y = curDelta , Component = ComDown } ) ;
120- VarianceView . Update ( price . Time . Value , "Variance" , "Sigma" , new AreaShape { Y = sigma , Component = Com } ) ;
121114 }
122115
123116 protected override async Task OnTradeUpdate ( Instrument instrument )
@@ -144,18 +137,24 @@ protected override async Task OnTradeUpdate(Instrument instrument)
144137 if ( orders . Count is 0 && curPositions . Count == 4 )
145138 {
146139 var options = await GetOptions ( instrument , nextDate ) ;
147- var ( curDelta , nextDelta , sigma ) = GetIndicators ( positions , point ) ;
148140 var isBuy = price > Strike && Side is OptionSideEnum . Put ;
149141 var isSell = price < Strike && Side is OptionSideEnum . Call ;
150-
142+ var range = Range ( price , IV ) ;
143+ var contracts = nextPositions . Where ( o => o . Side is OrderSideEnum . Long ) . Sum ( o => o . Operation . Amount ) / 2 ;
144+ var step = contracts is 0 ? 0.1 : Math . Max ( 0.1 , ( range / contracts ) . Value ) ;
145+
151146 if ( nextPositions . Count is 0 || isBuy || isSell )
152147 {
153- var order = GetNextOrder ( options , isSell ? - 1 : 1 ) ;
154- await adapter . SendOrder ( order ) ;
155- Side = isSell ? OptionSideEnum . Put : OptionSideEnum . Call ;
148+ var order = GetNextOrder ( options , isSell ? - 1 : 1 , nextPositions ) ;
149+
150+ if ( order is not null )
151+ {
152+ await adapter . SendOrder ( order ) ;
153+ Side = isSell ? OptionSideEnum . Put : OptionSideEnum . Call ;
154+ }
156155 }
157156
158- if ( price - StrikeUp > 0.1 )
157+ if ( price - StrikeUp > step )
159158 {
160159 var order = GetCoverOrder ( options , 1 , price , nextPositions ) ;
161160
@@ -166,7 +165,7 @@ protected override async Task OnTradeUpdate(Instrument instrument)
166165 }
167166 }
168167
169- if ( StrikeDown - price > 0.1 )
168+ if ( StrikeDown - price > step )
170169 {
171170 var order = GetCoverOrder ( options , - 1 , price , nextPositions ) ;
172171
@@ -237,29 +236,42 @@ async Task<IList<Instrument>> GetOptions(Instrument instrument, DateTime date)
237236 /// </summary>
238237 /// <param name="options"></param>
239238 /// <param name="direction"></param>
240- Order GetNextOrder ( IList < Instrument > options , int direction )
239+ Order GetNextOrder ( IList < Instrument > options , int direction , IList < Order > positions )
241240 {
241+ var countLongs = positions
242+ . Where ( o => o . Side is OrderSideEnum . Long )
243+ . Where ( o => o . Operation . Instrument . Derivative . Side is OptionSideEnum . Call )
244+ . Sum ( o => o . Operation . Amount ) ;
245+
246+ var countShorts = positions
247+ . Where ( o => o . Side is OrderSideEnum . Long )
248+ . Where ( o => o . Operation . Instrument . Derivative . Side is OptionSideEnum . Put )
249+ . Sum ( o => o . Operation . Amount ) ;
250+
251+ var noLong = direction > 0 && countLongs > countShorts ;
252+ var noShort = direction < 0 && countLongs < countShorts ;
253+
254+ if ( noLong || noShort )
255+ {
256+ return null ;
257+ }
258+
242259 var instrument = null as Instrument ;
243260
244261 if ( direction < 0 )
245262 {
246263 instrument = options
247264 ? . Where ( o => o . Derivative . Side is OptionSideEnum . Put )
248- ? . Where ( o => o . Derivative . Strike <= Strike )
249- ? . LastOrDefault ( ) ;
265+ ? . Where ( o => o . Derivative . Strike > Strike )
266+ ? . FirstOrDefault ( ) ;
250267 }
251268
252269 if ( direction > 0 )
253270 {
254271 instrument = options
255272 ? . Where ( o => o . Derivative . Side is OptionSideEnum . Call )
256- ? . Where ( o => o . Derivative . Strike >= Strike )
257- ? . FirstOrDefault ( ) ;
258- }
259-
260- if ( instrument is null )
261- {
262- return null ;
273+ ? . Where ( o => o . Derivative . Strike < Strike )
274+ ? . LastOrDefault ( ) ;
263275 }
264276
265277 var order = new Order
@@ -281,21 +293,21 @@ Order GetNextOrder(IList<Instrument> options, int direction)
281293 Order GetCoverOrder ( IList < Instrument > options , int direction , double ? price , IList < Order > positions )
282294 {
283295 var instrument = null as Instrument ;
284- var longAmount = positions
296+ var countLongs = positions
285297 . Where ( o => o . Side is OrderSideEnum . Long )
286298 . Where ( o => direction < 0 ?
287299 o . Operation . Instrument . Derivative . Side is OptionSideEnum . Put :
288300 o . Operation . Instrument . Derivative . Side is OptionSideEnum . Call )
289- . Sum ( o => o . Operation . Amount ) - 1 ;
301+ . Sum ( o => o . Operation . Amount ) ;
290302
291- var shortAmount = positions
303+ var countShorts = positions
292304 . Where ( o => o . Side is OrderSideEnum . Short )
293305 . Where ( o => direction < 0 ?
294306 o . Operation . Instrument . Derivative . Side is OptionSideEnum . Put :
295307 o . Operation . Instrument . Derivative . Side is OptionSideEnum . Call )
296308 . Sum ( o => o . Operation . Amount ) ;
297309
298- if ( longAmount - shortAmount < 1 )
310+ if ( countLongs - countShorts <= 1 )
299311 {
300312 return null ;
301313 }
@@ -316,11 +328,6 @@ Order GetCoverOrder(IList<Instrument> options, int direction, double? price, ILi
316328 ? . FirstOrDefault ( ) ;
317329 }
318330
319- if ( instrument is null )
320- {
321- return null ;
322- }
323-
324331 var order = new Order
325332 {
326333 Side = OrderSideEnum . Short ,
@@ -401,5 +408,12 @@ Order GetCurOrder(IList<Instrument> options)
401408
402409 return order ;
403410 }
411+
412+ /// <summary>
413+ /// Expected daily variance
414+ /// </summary>
415+ /// <param name="price"></param>
416+ /// <param name="volatility"></param>
417+ double ? Range ( double ? price , double ? volatility ) => Math . Sqrt ( 1.0 / 252.0 ) * price * volatility ;
404418 }
405419}
0 commit comments