-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tradier: new broker and data_source skeleton code added along with in… #325
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,69 @@ | ||||||||||||||||
from lumibot.brokers import Broker | ||||||||||||||||
from lumibot.data_sources import TRADIER_LIVE_API_URL, TRADIER_PAPER_API_URL, TradierAPIError, TradierData | ||||||||||||||||
from lumibot.entities import Asset, Order | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
class Tradier(Broker): | ||||||||||||||||
""" | ||||||||||||||||
Broker that connects to Tradier API to place orders and retrieve data | ||||||||||||||||
""" | ||||||||||||||||
def __init__(self, account_id=None, api_token=None, paper=True, config=None, max_workers=20, connect_stream=True, | ||||||||||||||||
data_source=None): | ||||||||||||||||
|
||||||||||||||||
if data_source is None: | ||||||||||||||||
data_source = TradierData(account_id=account_id, api_key=api_token, paper=paper, max_workers=max_workers) | ||||||||||||||||
|
||||||||||||||||
super().__init__(name='Tradier', data_source=data_source, config=config, max_workers=max_workers, | ||||||||||||||||
connect_stream=connect_stream) | ||||||||||||||||
|
||||||||||||||||
self._tradier_api_key = api_token | ||||||||||||||||
self._tradier_account_id = account_id | ||||||||||||||||
self._tradier_paper = paper | ||||||||||||||||
self._tradier_base_url = TRADIER_PAPER_API_URL if self._tradier_paper else TRADIER_LIVE_API_URL | ||||||||||||||||
|
||||||||||||||||
try: | ||||||||||||||||
self.validate_credentials() | ||||||||||||||||
except TradierAPIError as e: | ||||||||||||||||
raise TradierAPIError("Invalid Tradier Credentials") from e | ||||||||||||||||
|
||||||||||||||||
def validate_credentials(self): | ||||||||||||||||
pass | ||||||||||||||||
Comment on lines
+29
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||
|
||||||||||||||||
def cancel_order(self, order: Order): | ||||||||||||||||
pass | ||||||||||||||||
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||
|
||||||||||||||||
def _submit_order(self, order: Order): | ||||||||||||||||
pass | ||||||||||||||||
Comment on lines
+35
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||
|
||||||||||||||||
def _get_balances_at_broker(self, quote_asset: Asset) -> float: | ||||||||||||||||
pass | ||||||||||||||||
Comment on lines
+38
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||
|
||||||||||||||||
def get_historical_account_value(self): | ||||||||||||||||
pass | ||||||||||||||||
Comment on lines
+41
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||
|
||||||||||||||||
def _get_stream_object(self): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _register_stream_events(self): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _run_stream(self): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _parse_broker_position(self, broker_position, strategy, orders=None): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _pull_broker_position(self, asset: Asset): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _pull_broker_positions(self, strategy=None): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _parse_broker_order(self, response, strategy_name, strategy_object=None): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _pull_broker_order(self, identifier): | ||||||||||||||||
pass | ||||||||||||||||
|
||||||||||||||||
def _pull_broker_open_orders(self): | ||||||||||||||||
pass |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -6,5 +6,12 @@ | |||||||||||||||||||||||
from .exceptions import NoDataFound, UnavailabeTimestep | ||||||||||||||||||||||||
from .interactive_brokers_data import InteractiveBrokersData | ||||||||||||||||||||||||
from .pandas_data import PandasData | ||||||||||||||||||||||||
from .tradier_data import ( | ||||||||||||||||||||||||
TRADIER_LIVE_API_URL, | ||||||||||||||||||||||||
TRADIER_PAPER_API_URL, | ||||||||||||||||||||||||
TRADIER_STREAM_API_URL, | ||||||||||||||||||||||||
TradierAPIError, | ||||||||||||||||||||||||
TradierData, | ||||||||||||||||||||||||
) | ||||||||||||||||||||||||
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The import statements for the Tradier API URLs (TRADIER_LIVE_API_URL, TRADIER_PAPER_API_URL, TRADIER_STREAM_API_URL) might not be necessary in this file. If these constants are only used in the TradierData class, they should be imported there instead. This would keep the
Suggested change
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+9
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||
from .tradovate_data import TradovateData | ||||||||||||||||||||||||
from .yahoo_data import YahooData |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,35 @@ | ||||||||||||||
from .data_source import DataSource | ||||||||||||||
|
||||||||||||||
TRADIER_LIVE_API_URL = "https://api.tradier.com/v1/" | ||||||||||||||
TRADIER_PAPER_API_URL = "https://sandbox.tradier.com/v1/" | ||||||||||||||
TRADIER_STREAM_API_URL = "https://stream.tradier.com/v1/" # Only valid Live, no Paper support | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
class TradierAPIError(Exception): | ||||||||||||||
pass | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
class TradierData(DataSource): | ||||||||||||||
MIN_TIMESTEP = "minute" | ||||||||||||||
SOURCE = "Tradier" | ||||||||||||||
|
||||||||||||||
def __init__(self, account_id, api_key, paper=True, max_workers=20): | ||||||||||||||
super().__init__(api_key=api_key) | ||||||||||||||
Comment on lines
+16
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The class 'TradierData' inherits from 'DataSource' but does not call the parent constructor with all the necessary arguments. The parent constructor requires 'name' and 'config' arguments which are not provided in the child class constructor.
Suggested change
|
||||||||||||||
self._account_id = account_id | ||||||||||||||
self._paper = paper | ||||||||||||||
self._base_url = TRADIER_PAPER_API_URL if self._paper else TRADIER_LIVE_API_URL | ||||||||||||||
self.max_workers = min(max_workers, 50) | ||||||||||||||
|
||||||||||||||
def _pull_source_symbol_bars(self, asset, length, timestep=MIN_TIMESTEP, timeshift=None, quote=None, exchange=None, | ||||||||||||||
include_after_hours=True): | ||||||||||||||
pass | ||||||||||||||
|
||||||||||||||
def _pull_source_bars(self, assets, length, timestep=MIN_TIMESTEP, timeshift=None, quote=None, | ||||||||||||||
include_after_hours=True): | ||||||||||||||
pass | ||||||||||||||
|
||||||||||||||
def _parse_source_symbol_bars(self, response, asset, quote=None, length=None): | ||||||||||||||
pass | ||||||||||||||
|
||||||||||||||
def get_last_price(self, asset, quote=None, exchange=None): | ||||||||||||||
pass |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from lumibot.brokers import Tradier | ||
from lumibot.data_sources import TradierData | ||
|
||
|
||
class TestTradierData: | ||
def test_basics(self): | ||
tdata = TradierData(account_id="1234", api_key="a1b2c3", paper=True) | ||
assert tdata._account_id == "1234" | ||
|
||
|
||
class TestTradierBroker: | ||
def test_basics(self): | ||
broker = Tradier(account_id="1234", api_token="a1b2c3", paper=True) | ||
assert broker.name == "Tradier" | ||
assert broker._tradier_account_id == "1234" | ||
Comment on lines
+5
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+5
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Comment on lines
+8
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
__init__
method is quite long and complex. It's a good practice to keep methods short and simple for better readability and maintainability. Consider breaking it down into smaller methods.