mathpaquette / IQFeed.CSharpApiClient

IQFeed.CSharpApiClient is fastest and the most well-designed C# DTN IQFeed socket API connector available
MIT License
120 stars 43 forks source link

Add support for Dynamic Fieldsets #24

Closed jphiggs closed 4 years ago

jphiggs commented 6 years ago

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

mathpaquette commented 6 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.

omencat commented 5 years ago

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?

mathpaquette commented 4 years ago

@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

mrut2pac commented 4 years ago

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).

mathpaquette commented 4 years ago

man that sounds like an interesting idea.

BunkerCoder commented 4 years ago

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.

mathpaquette commented 4 years ago

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.

BunkerCoder commented 4 years ago

That would be awesome. Most of the headaches came from supporting multiple handlers!

mathpaquette commented 4 years ago

@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.

BunkerCoder commented 4 years ago

@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.

mathpaquette commented 4 years ago

@BunkerCoder please email me with your contact info

mathpaquette commented 4 years ago

ab49eefe04d74f3d8fe93f57c8338ae4370f556b fixed it. Thank you @BunkerCoder