Skip to content

Commit

Permalink
Added method for cancelling a pending/active order
Browse files Browse the repository at this point in the history
  • Loading branch information
shner-elmo committed Mar 9, 2023
1 parent 92b3bbb commit a6d0963
Showing 1 changed file with 70 additions and 1 deletion.
71 changes: 70 additions & 1 deletion tradezero_api/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

import pandas as pd
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver

from .enums import PortfolioTab, OrderType


class Portfolio:
def __init__(self, driver):
def __init__(self, driver: WebDriver):
self.driver = driver

def portfolio(self, return_type: str = 'df'):
Expand Down Expand Up @@ -58,3 +61,69 @@ def invested(self, symbol):
if symbol.upper() in symbols_list:
return True
return False

def _switch_portfolio_tab(self, tab: PortfolioTab) -> None:
"""
Switch the focus to a given tab
Note that this is idem-potent, meaning you can switch twice consecutively in the same tab.
:param tab: enum of PortfolioTab
:return: None
"""
portfolio_tab = self.driver.find_element(By.ID, tab)
portfolio_tab.click()

def get_active_orders(self, return_type: str = 'df'):
"""
Get a dataframe with all the active orders and their info
:param return_type: 'df' or 'dict'
:return: dataframe or dictionary (based on the return_type parameter)
"""
active_orders = self.driver.find_elements(By.XPATH, '//*[@id="aoTable-1"]/tbody/tr[@order-id]')
if len(active_orders) == 0:
warnings.warn('There are no active orders')
return None

df = pd.read_html(self.driver.page_source, attrs={'id': 'aoTable-1'})[0]
df = df.drop(0, axis=1) # remove the first column which contains the button "CANCEL"
df.columns = ['ref_number', 'symbol', 'side', 'qty', 'type', 'status', 'tif', 'limit', 'stop', 'placed']
# df = df.set_index('symbol') # cant set it as a column since its not always unique

if return_type == 'dict':
return df.to_dict('index')
return df

def symbol_present_in_active_orders(self, symbol: str) -> bool:
"""
Check if a given symbol is present in the active orders tab
:param symbol:
:return: True or False
"""
return symbol.upper() in self.get_active_orders()['symbol'].values

def cancel_active_order(self, symbol: str, order_type: OrderType) -> None:
"""
Cancel a pending order
:param symbol:
:param order_type: enum of OrderType
:return: None
"""
symbol = symbol.upper()
self._switch_portfolio_tab(tab=PortfolioTab.active_orders)

df = self.get_active_orders()
assert symbol in df['symbol'].values, f'Given symbol {symbol} is not present in the active orders tab'

# find the ref-id of all the orders we have to cancel:
filt = (df['symbol'] == symbol) & (df['type'] == order_type)
ids_to_cancel = df[filt]['ref_number'].values
ids_to_cancel = [x.replace('S.', '') for x in ids_to_cancel]

for order_id in ids_to_cancel:
cancel_button = self.driver.find_element(
By.XPATH, f'//div[@id="portfolio-content-tab-ao-1"]//*[@order-id="{order_id}"]/td[@class="red"]')
cancel_button.click()

0 comments on commit a6d0963

Please sign in to comment.