Open perigvennetier opened 3 years ago
I was missing the listing/creation/deletion of alerts so I added that as well.
I also just added the missing capital/margin requirement API call and example
Thanks for all the comments. I hear all your comments about things being already in the classes we have.
I think there may be some confusion about what my intent for this was.
My idea was actually the other way around where the modules would be updated to pull data from this, even the session module/class because this would be the ground truth for all low level API calls so api low level interface is not spread around in all the classes. Easier for maintenance and future proof.
That's fair. I think the argument could also be made that the models themselves are API endpoints.
That's fair. I think the argument could also be made that the models themselves are API endpoints.
I absolutely agree and I think we're seeing two overall implementation architectures.
I still feel have all the API requests being all spread out and left to be discovered in the various classes make it a bit hard to use. It definitely took me quite a bit to figure how all the piece are fitting together as it is.
I still strongly feel that having one module working as an abstraction layer between the TW API and the classes that handles all the API interaction is a lot cleaner and easier to pick up to add new classes and methods. If this is in place, to create a new "Stock" or "Journal" or "Alert" class would be super simple because all the API calls are already handled and raw data is returned.
This layer, providing (almost) no filtering from the data returned by the API leaves all the flexibility to the classes to have more diverse and simple methods to apply to the returned raw data. All the formatting and filtering of the data and more useful features of classes and method would still belong to the classes themselves.
PS: It seems what I am proposing here is quite similar to how the streamer is handled where all the interfaces and calls to the streamer are in the DataStreamer class.
@boyan-soubachov, @bandwiches, I hope you guys like this.
Going through the current base code I noticed that the calls to the TW API seems to be spread out throughout the entire code base making it a bit hard to find out what features were already available and which were not, what URLs were used, what methods to communicate to the API were used, etc. and would make it really hard to update if there was changes made in the server side API and if/when they finally release their API officially.
So I decided to create a new base layer module that includes all the low level TW API URLs/features/methods currently available via the server API. This low level module does not depend on any other created module and so it is self sustaining. In order to achieve that I decided to only pass the session token to the included methods and not an entire session object. I don't believe there is a real downside to doing this and it avoids having to pass username and password around.
I also created a new example_api file that runs through all the API calls. The example file does not use any of the classes currently implemented to keep it as low level as possible with no application specific import requirements.
WARNING
The example will route a real order, modify it and then cancel it. It will not be filled as I picked a price that would not fill but it will show in your account.
Requirement
This new example relies on an additional system environment variable TW_ACCOUNT in order to be able to run without having to fetch and pick the right account and modify the example code. As long as the 'TW_ACCOUNT' variable match a valid account number, the example will run. The call [environ.get('TW_ACCOUNT', "")] can also be manually be replaced with hardcoded account number as a string in the example_api script to run.
The new module includes
make_api_url(): A method to dynamically create all the URLs available in TW API based on the various calling functions and various passed parameters like symbols, dates, IDs, pagination, etc.
api_request(): A method to send the HTTP requests to the server API and read the response, returning as raw a response as possible to end-user can choose what to use and discard. I did not keep 100% of the response data as I could not figure out how to dump all the response data at once. So I crafted a new response with all of the data I could think would be useful to have (the payload of course, the status code, response OK or not, the response reason and a few other)
is_error(): A very basic method to do only error printout when HTTP requests return error codes. It is very limited. I decided to not raise exception when error happen in order to continue with execution but will print out errors when they happen. This is very basic and we may want to create a separate real error handling module that can be called from all the other classes (one unified error handling module that would understand the various error returned by the server API like error in HTTP requests but also error codes returned by the API responses like 'opening_market_order_unavailable', 'stop_future_option_order_not_allowed', 'gtc_market_orders_not_supported', etc.)
All the available API features I could find and related functionalities (list, create, modify, delete, pagination)
Missing
Features implemented
Problem addressed
The calls to the TW API seems to be spread out throughout the entire code base making it a bit hard to find out what features were already available and which were not and would make it hard to update there was changes made in the server side API and if/when they finally release their API officially.
Solution
New low level module.
Checklist