1414*/
1515
1616using System ;
17+ using System . Text ;
1718using System . Linq ;
1819using NUnit . Framework ;
1920using System . Threading ;
@@ -54,16 +55,61 @@ public void TearDown()
5455 }
5556 }
5657
57- [ TestCase ( "AAPL" , SecurityType . Equity , Resolution . Second , 0 , "2024/08/16" ) ]
58- [ TestCase ( "AAPL" , SecurityType . Option , Resolution . Second , 215 , "2024/08/16" ) ]
59- [ TestCase ( "VIX" , SecurityType . Index , Resolution . Second , 0 , "2024/08/16" ) ]
60- public void CanSubscribeAndUnsubscribeOnSecondResolution ( string ticker , SecurityType securityType , Resolution resolution , decimal strikePrice , DateTime expiryDate = default )
58+ private static IEnumerable < TestCaseData > TestParameters
6159 {
62- var configs = GetSubscriptionDataConfigs ( ticker , securityType , resolution , strikePrice , expiryDate ) ;
60+ get
61+ {
62+ var AAPL = Symbols . AAPL ;
63+ yield return new TestCaseData ( new Symbol [ ] { AAPL } , Resolution . Second ) ;
6364
64- Assert . That ( configs , Is . Not . Empty ) ;
65+ var DJI_Index = Symbol . Create ( "DJI" , SecurityType . Index , Market . USA ) ;
66+ yield return new TestCaseData ( new Symbol [ ] { DJI_Index } , Resolution . Second ) ;
67+
68+ var NVDA = Symbol . Create ( "NVDA" , SecurityType . Equity , Market . USA ) ;
69+ var DJT = Symbol . Create ( "DJT" , SecurityType . Equity , Market . USA ) ;
70+ var TSLA = Symbol . Create ( "TSLA" , SecurityType . Equity , Market . USA ) ;
71+ yield return new TestCaseData ( new Symbol [ ] { AAPL , DJI_Index , NVDA , DJT , TSLA } , Resolution . Second ) ;
72+
73+ var AAPL_Option = Symbol . CreateOption ( AAPL , AAPL . ID . Market , SecurityType . Option . DefaultOptionStyle ( ) , OptionRight . Call , 220m , new DateTime ( 2025 , 06 , 20 ) ) ;
74+ var AAPL_Option2 = Symbol . CreateOption ( AAPL , AAPL . ID . Market , SecurityType . Option . DefaultOptionStyle ( ) , OptionRight . Call , 217.5m , new DateTime ( 2026 , 06 , 20 ) ) ;
75+ var AAPL_Option3 = Symbol . CreateOption ( AAPL , AAPL . ID . Market , SecurityType . Option . DefaultOptionStyle ( ) , OptionRight . Put , 220m , new DateTime ( 2026 , 06 , 20 ) ) ;
76+ var AAPL_Option4 = Symbol . CreateOption ( AAPL , AAPL . ID . Market , SecurityType . Option . DefaultOptionStyle ( ) , OptionRight . Put , 217.5m , new DateTime ( 2026 , 06 , 20 ) ) ;
77+ yield return new TestCaseData ( new [ ] { AAPL_Option , AAPL_Option2 , AAPL_Option3 , AAPL_Option4 } , Resolution . Second ) ;
78+
79+ var nok = Symbol . Create ( "NOK" , SecurityType . Equity , Market . USA ) ;
80+ var nok_option = Symbol . CreateOption ( nok , nok . ID . Market , SecurityType . Option . DefaultOptionStyle ( ) , OptionRight . Call , 7.5m , new DateTime ( 2026 , 06 , 20 ) ) ;
81+
82+ yield return new TestCaseData ( new [ ] { nok_option } , Resolution . Second ) ;
83+ }
84+ }
85+
86+ [ Test , TestCaseSource ( nameof ( TestParameters ) ) ]
87+ public void CanSubscribeAndUnsubscribeOnSecondResolution ( Symbol [ ] symbols , Resolution resolution )
88+ {
89+
90+ var configs = new List < SubscriptionDataConfig > ( ) ;
91+
92+ var dataFromEnumerator = new Dictionary < Symbol , Dictionary < Type , int > > ( ) ;
6593
66- var dataFromEnumerator = new Dictionary < Type , int > ( ) { { typeof ( TradeBar ) , 0 } , { typeof ( QuoteBar ) , 0 } } ;
94+ foreach ( var symbol in symbols )
95+ {
96+ dataFromEnumerator [ symbol ] = new Dictionary < Type , int > ( ) ;
97+ foreach ( var config in GetSubscriptionDataConfigs ( symbol , resolution ) )
98+ {
99+ configs . Add ( config ) ;
100+
101+ var tickType = config . TickType switch
102+ {
103+ TickType . Quote => typeof ( QuoteBar ) ,
104+ TickType . Trade => typeof ( TradeBar ) ,
105+ _ => throw new NotImplementedException ( )
106+ } ;
107+
108+ dataFromEnumerator [ symbol ] [ tickType ] = 0 ;
109+ }
110+ }
111+
112+ Assert . That ( configs , Is . Not . Empty ) ;
67113
68114 Action < BaseData > callback = ( dataPoint ) =>
69115 {
@@ -74,13 +120,18 @@ public void CanSubscribeAndUnsubscribeOnSecondResolution(string ticker, Security
74120
75121 switch ( dataPoint )
76122 {
77- case TradeBar _ :
78- dataFromEnumerator [ typeof ( TradeBar ) ] += 1 ;
123+ case TradeBar tb :
124+ dataFromEnumerator [ tb . Symbol ] [ typeof ( TradeBar ) ] += 1 ;
79125 break ;
80- case QuoteBar _:
81- dataFromEnumerator [ typeof ( QuoteBar ) ] += 1 ;
126+ case QuoteBar qb :
127+ Assert . GreaterOrEqual ( qb . Ask . Open , qb . Bid . Open , $ "QuoteBar validation failed for { qb . Symbol } : Ask.Open ({ qb . Ask . Open } ) <= Bid.Open ({ qb . Bid . Open } ). Full data: { DisplayBaseData ( qb ) } ") ;
128+ Assert . GreaterOrEqual ( qb . Ask . High , qb . Bid . High , $ "QuoteBar validation failed for { qb . Symbol } : Ask.High ({ qb . Ask . High } ) <= Bid.High ({ qb . Bid . High } ). Full data: { DisplayBaseData ( qb ) } ") ;
129+ Assert . GreaterOrEqual ( qb . Ask . Low , qb . Bid . Low , $ "QuoteBar validation failed for { qb . Symbol } : Ask.Low ({ qb . Ask . Low } ) <= Bid.Low ({ qb . Bid . Low } ). Full data: { DisplayBaseData ( qb ) } ") ;
130+ Assert . GreaterOrEqual ( qb . Ask . Close , qb . Bid . Close , $ "QuoteBar validation failed for { qb . Symbol } : Ask.Close ({ qb . Ask . Close } ) <= Bid.Close ({ qb . Bid . Close } ). Full data: { DisplayBaseData ( qb ) } ") ;
131+ dataFromEnumerator [ qb . Symbol ] [ typeof ( QuoteBar ) ] += 1 ;
82132 break ;
83- } ;
133+ }
134+ ;
84135 } ;
85136
86137 foreach ( var config in configs )
@@ -92,7 +143,7 @@ public void CanSubscribeAndUnsubscribeOnSecondResolution(string ticker, Security
92143 } ) , _cancellationTokenSource . Token , callback : callback ) ;
93144 }
94145
95- Thread . Sleep ( TimeSpan . FromSeconds ( 25 ) ) ;
146+ Thread . Sleep ( TimeSpan . FromSeconds ( 60 ) ) ;
96147
97148 Log . Trace ( "Unsubscribing symbols" ) ;
98149 foreach ( var config in configs )
@@ -104,20 +155,40 @@ public void CanSubscribeAndUnsubscribeOnSecondResolution(string ticker, Security
104155
105156 _cancellationTokenSource . Cancel ( ) ;
106157
107- Log . Trace ( $ "{ nameof ( ThetaDataProviderTests ) } .{ nameof ( CanSubscribeAndUnsubscribeOnSecondResolution ) } : ***** Summary *****") ;
108- Log . Trace ( $ "Input parameters: ticker:{ ticker } | securityType:{ securityType } | resolution:{ resolution } ") ;
158+ var str = new StringBuilder ( ) ;
109159
110- foreach ( var data in dataFromEnumerator )
160+ str . AppendLine ( $ "{ nameof ( ThetaDataProviderTests ) } .{ nameof ( CanSubscribeAndUnsubscribeOnSecondResolution ) } : ***** Summary *****") ;
161+
162+ foreach ( var symbol in symbols )
111163 {
112- Log . Trace ( $ "[{ data . Key } ] = { data . Value } ") ;
164+ str . AppendLine ( $ "Input parameters: ticker:{ symbol } | securityType:{ symbol . SecurityType } | resolution:{ resolution } ") ;
165+
166+ foreach ( var tickType in dataFromEnumerator [ symbol ] )
167+ {
168+ str . AppendLine ( $ "[{ tickType . Key } ] = { tickType . Value } ") ;
169+
170+ if ( symbol . SecurityType != SecurityType . Index )
171+ {
172+ Assert . Greater ( tickType . Value , 0 ) ;
173+ }
174+ // The ThetaData returns TradeBar seldom. Perhaps should find more relevant ticker.
175+ Assert . GreaterOrEqual ( tickType . Value , 0 ) ;
176+ }
177+ str . AppendLine ( new string ( '-' , 30 ) ) ;
113178 }
114179
115- if ( securityType != SecurityType . Index )
180+ Log . Trace ( str . ToString ( ) ) ;
181+ }
182+
183+ private static string DisplayBaseData ( BaseData item )
184+ {
185+ switch ( item )
116186 {
117- Assert . Greater ( dataFromEnumerator [ typeof ( QuoteBar ) ] , 0 ) ;
187+ case TradeBar tradeBar :
188+ return $ "Data Type: { item . DataType } | " + tradeBar . ToString ( ) + $ " Time: { tradeBar . Time } , EndTime: { tradeBar . EndTime } ";
189+ default :
190+ return $ "DEFAULT: Data Type: { item . DataType } | Time: { item . Time } | End Time: { item . EndTime } | Symbol: { item . Symbol } | Price: { item . Price } | IsFillForward: { item . IsFillForward } ";
118191 }
119- // The ThetaData returns TradeBar seldom. Perhaps should find more relevant ticker.
120- Assert . GreaterOrEqual ( dataFromEnumerator [ typeof ( TradeBar ) ] , 0 ) ;
121192 }
122193
123194 [ TestCase ( "AAPL" , SecurityType . Equity ) ]
@@ -152,7 +223,7 @@ public void MultipleSubscriptionOnOptionContractsTickResolution(string ticker, S
152223 case TickType . Quote :
153224 incomingSymbolDataByTickType [ ( tick . Symbol , tick . TickType ) ] += 1 ;
154225 break ;
155- } ;
226+ }
156227 }
157228 } ;
158229
0 commit comments