Closed jphiggs closed 4 years ago
Hello @jphiggs , you're correct. Out of the box, this thing isn't already supported. I'll try to add the support this in the very near future. I have some ideas how to deal with it.
I just ran in to the same issue when trying to add OpenInterest to my dynamic fieldset. So it looks like ad5a2b0e60c204a1a184d700579c054934265d9a added the support to generate a proper S,CURRENT UPDATE FIELDNAMES
, and it works, I can see the open interest. I guess the next step is an update/overload to the UpdateSummaryMessage because the fields are hard coded. I've never used dynamic fieldsets before. Is it just a matter of passing the new dynamic fieldset?
@omencat unfortunately this is a little more complex than just that. We also need a dynamic way of parsing values and more importantly create UpdateSummary object without affecting too much the performance of the application.
That being said, maybe I should provide an example of how to custom dynamic fields
I thought about this. We can use Runtime Code Generation using classes from Emit namespace - https://www.nikolalukovic.com/programming/net-dynamically-generating-classes-in-runtime . If we define an interface for UpdateSummaryMessage, our class generator code can take the selected fieldset and dynamically create a Class that implement that interface. For every field that is not selected there won't be a backing field (to save memory) and the corresponding getter property will just throw NotSupportedException. Parse method code will take the message and properly assign to the needed fields. Other methods (constructor, Equals, GetHashCode, ToString, etc.) can be easily generated. If the fieldset is changed, we will generate a new class. The good thing about this approach is that we generate a class once and reuse it during the lifetime of the application. No reflection needs to be used run time and we get optimal memory utilization (no redundant and used fields in the class) and max performance (no need to parse longer strings and assign to the fields that are not needed).
man that sounds like an interesting idea.
I'm under the gun to get this working, so I'm working on an implementation. My solution is a bit more simplistic than the ideas offered by @mrut2pac, but it should be fast, although a bit verbose. I'm new to the GIT world. I forked the repository and pushed up a branch with my initial design ideas (INCOMPLETE). I'll create a PR shortly. I'm planning to continue down the road that I've started, but I'd like to get feedback on the design. Thanks to you folks for the awesome work.
great! but keep in mind that Im going to remove the support of multiple handlers (float, double et decimal) and only keep as default double for code simplicity.
That would be awesome. Most of the headaches came from supporting multiple handlers!
@BunkerCoder yes. This added too much complexity for the benefit added. I think I dont want to touch the current Level1Client but might be a good opportunity to add a Level1ClientDynamic using dynamics instead.
@mathpaquette - I pretty much trampled all over Leve1Client, but it's fairly clean. Let me know if you change your mind after taking a peek. I'm committed to doing the work, so I'd rather do it in a way that will actually get pulled. Much appreciated.
@BunkerCoder please email me with your contact info
ab49eefe04d74f3d8fe93f57c8338ae4370f556b fixed it. Thank you @BunkerCoder
It looks like there's an issue with using dynamic fieldsets. Sending the following requests works level1Client.SelectUpdateFieldName(DynamicFieldset.MostRecentTrade, DynamicFieldset.MostRecentTradeSize, DynamicFieldset.MostRecentTradeTime); level1Client.ReqWatch("@ESU18"); but an exception is thrown trying to parse the update message because it assumes all current update fieldnames are present. After the message split there's then an array bounds exception. See IQFeed.CSharpApiClient.Streaming.Level1.Messages.UpdateSummaryMessage.Parse