Skip to content

Commit

Permalink
🧼 chore(trade): abstract fxs and improve typing 🧼 (#248)
Browse files Browse the repository at this point in the history
* is not equal

* clean up

* fill orders fx

* add types and tests

* #patch

* use Union for multitypes

* Update Calculus.py

* pin plotly version for vectorbt

* try this

* again

* datetime

* array
  • Loading branch information
alkalescent authored Jan 30, 2025
1 parent 8b9aa90 commit d5fc942
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 21 deletions.
2 changes: 1 addition & 1 deletion encrypted/optimize_portfolio.py.encrypted
Original file line number Diff line number Diff line change
@@ -1 +1 @@
gAAAAABnk1xQzWSAT0Vf77Vrl7IWhzfgK3L0X4FssVTP-qNrVZMuniiANHgTeRl1RJDmImV3BPA4ZHu7AsOP3QryfS3dE31h0ggfBio4we76ui3VqgJqgzt2P7AA3U7bxdZXQDd6peKShMDJDO6ssYflmGEpgYkpSSHezcYxVq3x5hmew1TYBl0ssOqKID9lrV9ZesO8TWcNGHEo4AE53kBq0K-3vA51MWrGXM9qCS2IuVXoV6yuAKryju97rMu7kFwnKIEgg8DuQqmWSI9f7acUHzuFK4vOSmgryJxGdXvqwshy822n94xLnRPEpQHaeTEVyoJRtA3gnu3Q1FOg6Z7Xe1Ne_lY3dmn8KBrt9ghf5GmbAefKllsW-dDhutL--5vdBgSBu0WcqqXE2LGXM2-g-Vlc4MBmtyJGv1icP6MRFbV0vKd5KlTwD-3hcSxDkqUsU5-xSojeXuXHsvvP0nPIrZJXSJgAkmYtQ4y5dRjPKsg3qQd_g7YXsblzH9GQufcd891k4aAQrQNMjKOlUiNycduxC0bsWuDBsEGBYh7kVh43oOJZOrCX8h-JfKxJWU3k82fJkDhdTGSVVD62BsK77s1FkwbV6NGQk-HCyxFat6j4u8byB-HDXG8xGx5FwH0OdgZHcEuOrDo4JUsagJ_D61Ooo2ysuvVu0V-xTU660nkqg6t14kPl2aXzHWlAjv6mrKgvFYD56XJ1HD7uuRJWdwtDi2ANfnYBWyzYx26R_fCjnaBGb_n_CNZtc1rz933Ssky9WvUu3FduAJ7RV4Y0aqBJ17BXrT_HEpdr7kAIijqp60lDh0U2CZ7I-6gwJ0LhqNWqL_xnH8YIKkPoVh-9Hx7UaIHtmxJrVihsdtZOS6T_b5OduL3rv4K1i6vspoTSqyywlFaTXVLppFTepHoXUR1ep4z9mPfiSrYlyvD9L0OWAXt5sk78yELF0MBQa7wvRHxP3sLAke0kgVZwjdBKB5uECdpDgDlmzS8A9ZxvH2xs4ImgUqm_kDN4EhB45M1Go3UJWeo8HwHBQ1Y7avCORX7OIDYOjXdjVw31lhiUNYlVVgBuUTi2AM4wMgmMgIR_QrYxC414VRPQ8K32R0MoyBD5DrTZH7-ptFa9PxtTrN7D_sMK8khrIKv4HYZ6ysKRNifoQVeucriNt6URRJtGfMlHgk9oqi7uClfRHfObbchw6biXgrJIAlvOIFO7EzO6_SWkqYjTF2zxZL_wTJA-EkNSsIwxpL4gXlIRpNTAaf8EZw17fYpFmy_GA4RL8tbjku3q7Ik55mhsgK_D5eLMuJmj_qy_q4zs5BMAikfPguP-E7NlNS62TIGTwsHOKt6uMgPDAGL3TEwEIYkx9GmJnGJ-mDYD5mJI400BWj_4LIh3e-J1VwcCdzGBa04rVEyXz0YzTiAG4O2gWQrrPnTw1ZeWaqmNG9_pFJF5tuWR1BYk95qM0VBWIkmJPnpDRZRPn3Eso74TgwmlfIRVtjKyWyI_ZGOIJwK3WrAUwG-W-OxEnzdqp-sTjZNF-R2AGD-VlkZev9L_jWNFKibdlmXW1zRmy_A7w-_Jg5cQ5lpr4ggBsjDwx8sHaUlVjd6CLgrM2knJPQJRac2YYOYGGyeCj3IkebDHv9LeckUieNGdajmV6pooIyyXEp0BFWn16YOGmVxC1Rs0H0pnd5eiZq5HdKZ1Vy_FQAufUGKyXn_OZ0DUfeq-Aw5gZF4qqZOsniv-caVc4Du8I8SsFT5SwJ2Sq2RwUfWEiprrR38oOB8TPeaaOhd2veYdn77c9x7AsvsZvQnPjFj3rAIv9Q3g8i79-x4GsaLrhYx12_zs9GlNJPr0kHHFD1a0hpPxjR13azGoNy-N-5Oci7GbaAQDZttq9dfx4Y5M18H3DLupnhU421P8jikJsKIT8f4xns7G8a3lbKRoB2gge3y8H58vHhvmQKjwd_lFeQJaD-Ix2wNH2uyh9H1YKYhTg10c4nIa1IxohyMmyIrfCGdVFM_hRLOv2nd3Dn4Mtd-Ad-4Tksml0t39RX5npcEEvFfzEeoO4A5ci2GGS8mHtNV6_s9KhTd7p_Ch82X6PFz6AetlTeNmjT46xYypjlTHvTp5qqgVs9F-gvy0LeR4oywq3iAL8a-_HmtXXRUqqi5j0gRySIEiF4wsjz4t6F3DPtyrQcKLtdN1d1ZwMi6GUXsZS5dp7grC7l72elEDV66KvvrUx-BVSPAhPN5nN_lyTkXgOu_yWGhR2u7q5fGJQfwZrmhlabNPLNgOn7fee69AGMWvfGeVGwTCaY68NWIWpDOo4Su0VEM11HqTVnhunXt9a-jUNQgFJxWyBmQRbGRUs8nvYLj4InK_uh3hxfbZQwBOqpMFeg3c-TZk-yaksGp57pD1t5PVPCyMjZVJSQhyQewHqwzgMsANsh3ZpeVKVR2-PhouKFKpDRVpnl5gWMovD4aXUhMdyA1xIdVnZ9sSH4bLkCtqixJ-_yvMnAIu-PMAzooPLV9cYpBoUPTNYUYesgya0q5WfKyDvYrCd23yIy98YO4H5I_Yz7EFwj895ca3p1r5pxxO1HxHBUgB3pwlsPkDWh4DfFVKEtTHiO1it3c-mEZVeWCOQArmV-4O6tTsAk6zsPdcYYdPRMjrMtLGqNgDQNY_lNE08TIqIi48-NkN4yZB9UFE6mZdjrxvsMbeyE2yPPbkqVpdQ-IdSECjekXS10v5nUzmu0ZA-JXsev8oItVn8BtmalnbYdx5dQDpUakBhjrAHMbQB2FYp2DxnXop6vBtNTi_9mC6IdkuoKgJda8TChFp7ab7O1yoRlq8m4OK66xseH_gyfmocroDmlIRDl9En7o8Pz4XPOImtkr3gDPA7Pi5aEqxpoRkZxmApPHtTP3Tp6QWS0VQzFYHwQDv-L8rpffvvZ0z7g21G6ozH3g0Y1b5CJlMxFRyx9b2tOn3L4g0iRAZ1EtU-AzVLhc5NEIiVofIcfMXCzsamf0lCGCfOSE7xGgHHfM4vyGo07OvZdEg9kqfOTaIeM6meR9G0W5LR0zwRGuvAL4Weg575rIrq-AQoRkiXJIG55fjJNKwx8s1wzD5Q6vCoBOzfWMVuoSlC3HpUMXWTiItq5fHKU_oSutWFdrdJ7gLSbLRJzdTO7DH00Wnu4lh-KBStDJxbkOjxzuefnT6RHgNbdJUBtBLoMGbtdcjLLjZFrhR2s8BpbT-3Axc91EyqgD23a3GO5reOVnOL89t-g0XknKVplCArvHXI6hjkCvi6BuNna4TVkKVJOp_n9fnDw0sXL1quyH6nBp7OZ-fyl2VskgWbEbZPLpD4xDTo2siKSGcKkM_Dqmzt9njagifVQPj828dI0Fb7YjByqwwDjedUz0Z3Is9tHGAp0EdXJEbQNhxivqgAu8DVd83Ghc5kRXnzs-bxbWBjxiLb_oFqi_yxLevtav8y1_de9sZZ45ZYyVOLvueAGl3T8FajeSqEsGCIK0tF2dIfXDIEG5xwjp8nE0hK8XxAJ7aDp3CILp-TaKVZ7Sgc2HsWlDR5XzweeYIqyicIdYBOJ6uPxZJfRfZqeVm1axSYWlHaUKhFsgCrOVZGWM-EnZoO-AYR3Yh_xI_Oek-Te9tEPUS5JAH3vSlsXH9nh-TfhQI02Qbr3uvIsJGPKnusqk23hW51P_vsXGpHelAE6Ea-gAfvac-7BrcVWmEX98MSm_BLcxGthftfFtOaZNfcdmVn_F5czeXPCohA7fzYOK8-Miavhb47l0lL8zR0fWhrRU0ylCZTXESlZStiC6UbPvzN-QtOq0-BU7S_i5MAdNE5MOH47D3PEscQjIv2p4D8xPRTnRzvFqFM9Rl3M8HU9xbDum3_cg_rCWURwWQxwrvoGy_kQq1Vl2cz03vOmkUfCMmiGuqI0Q2kL8Sex8ZilUFKmMu4-zFvTaOoQy9eSC-yqUNp8CFDG0B7C0zYYCT96NszR4YS-EH-EfCNYBFbbeTA-EANb8ZWitMPS3skqpAwIl3dVcGyRCBqb1vtMiSrbyywQVijlk=
gAAAAABnmrgIvwHeEx5jfz5a6XRewid4KE0mMzTdJeuk3j-71_BacgaeHHp7UTBlhUe5FkcQKPiPh1_ZLGQEZ-KTyPmvGaRNk-MGC5hNGwJl1KqXJdnLYM4-Z43Prj8AL40uDfM5teGdniR0UKjZ_dnjNYp88C8h4HfTYJj_zBdVmfAvypu1rVQqgyNm_A2pQAANlcpjxIqgYjIH3D_Nnl0i42SZ6dIaFT_3dOF24Jxi0NauxZkfMuIYmQ8hdHugLlYIgAwEjG-fWnt_CffkI682yjMpZCPQDrblmar4slLMG_y37-B3XoqPa_Ho2xsyKF9tSF3lANdWTMYa8zPN5b7CxIJ6OIAPHRRHhuYmourEKN9ij-S4T91PTKTQHRfxFJ0-i_Imyup4gEipjVE53J5Briofy8BTsja9o1daHv84stFGE80lRQLXLy1eul33pWCenVbI7KfToNmUhuo_8T6uyCrrqbB6aDMYWi3gZadZ8GZpy5yBtj2ojNHpSA9HUBk_nfpbelA-qvHXaXOVhGn5RlN-KnoAz6qZI0XEMTLdDxKCTgQZrFoz_6kmKNNQmmao4CalKA-Q1f3EhQ5BcitsCCragiFVYxxjH-eWUXPyeJaqWNCUJ3tSaNIWSsyDKHlxo8mgCV5Z0IkSSDgHtkqgxZB4Kch3_5HKoh2jWRHep3GPTdD2HeQYRYR74LV_iZuAUqA9kJ6S-uEcsClA1NI3d5FZtdJ6AjI4XXXi0J463dhYHBWAZUocyi8qTs82PYmmhTuE_t2ehpgwMGIaKE73097IJ7jonfd_SXjVKERm5yYXU1w9LOeKMo8XVIixkl5NqXuzUjO8s2pZGCwrT7M3x_Ki1XdqQ_InljUgX-I1h_VOamh4VYr_sUOdPHhAHVXrPOoRdY3N5k1-glmdpRGAuVSpxzgnp1eDZedmX4QhMBEO-geldoW9kEkwK8npioObA06dQxymy4Mmy86FvFb0e5jgmEFC7wAjNsncznnMqdpM-kAYMNMteVLrwrFkyR44ar1AmPMs9OHzAZOFOtQsaMRN8QrXL7NNpmsVQMEsSaQI1O4CSChpoZ6byqdbtWNj26P307SuFfK6-XaxF3ZF8OPLxH__96502tz_JcKOICKYuq1671WwlsdhF14Mqbe5V-2y6dcDugxjUT3lNx4ePBhlf2F6rITDRAwwo-K_uh7BnWPwhCgBQXFKWU0sP6lkGL5-nDmeSNLR3inmOImy0iy_DtAwXOFspEn4bmWinD6-JDZkvtoTsW4g3pRGytP0cPqTbTQFOibf0G4faiUhzJZ0pIghP3oOzRB1rzflpWYJPfkw7M6OoMVM34sDmQM2UEqFnCeBMXzYNGhfGgfcYIxMpCPUh2ti9gPA-r4jHv4wnL3FpLNyAwKFD9FYL2n9L9YodxBD63lze_tavQkfEMOUilAiS4ym18qsviIpH4HUqIW0NR54sayAaVaHfoPkBB14fb9eeaFcpgoJDfeFMaSqf4h-zWscNnaekYt1tRN5zSrLDWmsh-qYTvErvycX_IAlz0qmgpo-Xh3zhKsk-ldPeXB40COjyO1AAEQRBDb65E7uhW9CCu6OoPyYujqejw29o0qadi7VaB_gMb4OZ636Yw_La5rI0UTl1pDw2fUD5_BXsM50ibRyxGiOmaI8PXmb55DunDdBwyPxD7LUCP-MY0LLMC15SE2grhwJRD7eJ4zfDg7B7MibQPnycjLRj63lpUKw3lp1deKiV8ZYH3ElO2Ertxb119RhSOT0CXrx4kOR-bXyjNO3J1iCF0c16fnCHY1dG-O7cKEa682hwG4HY6tS-gj8oX69g1dsembmWu-7WN59Az90WznGCZPops0Ngkqe1ZaWdbBBpPrrU0m7IIsADjJXiS8q4nlIzj34L2WxtO0OBv-RnaLAEfsnDTM5_cB5dowF66uR16prPqTqJVs1k1ybaEkvIs00kPfa4nUAy6J6m8Z762SFP7m2dytdwGT7Hc2FDU-w6Zj2Fs4sfqVpUXl4BLKug08-KY7BaJTuCtIxFtnuzgIB0nDzuhqLvq7KafNbzOaQSn6NTb1zQ7YYIg_Z55BzPTFe9jK78eue1OSBPDLiSuXBtzpfOakh969aKhAYWy_5TNW38pt31T1qrsV7y40OMC3ZcBmJmUX5WsqH_kjUIelLUap5ajVDdKbKQCxZpOmMpkhUc86jju--mNR3CdwXKpKUublrK93ERz-HxW9CKcTuBg9bd0tadygfOd1DBo_3gu2mwXGuFy2qx_WIUuq4V5L2V9a9HDKWCbI46m2u8B5NZtBGjTwdqjENpIK7hJ-hjaq18mqj8y3844U7oQfvJ1lm1dPGCNwJG9E98iRlox51Yr3-KAz7cZn_n1GjV1gf9paGhrFthjCost8uiqUZVKEZxxMYeZnorZO-yfLckDyXxCC5v9uD45HKiiyKgeY7_qyCP2idgNdI39rLlW6bhXHgaTnLMul6QHWAe9BPVT0H-YNcpn9MUbocbVBL_Xcf-NMDGXqNc40TUg9wGfzWes7oYdL2Gu_pTYUtEa9ojuQ5ulSmiaIvzo5WFAqGs5W4LgpJbZ6CeaCZFSA77V8ejsNdckFOxG9dqx32c3_TcaFEatDFhhjCM5ACadD-axbp4Mqb6kmyJKHYksIwgUQi6ehWD4cfEvgQPDv5g-GSwkyC22h9PrD5Vzl5H8KpasaAS2tj47SsgVGkOA9RRmlE3Nnmll6ZbyEL6GblqPLsFcGTNrLL9kT36KtjF98joYou3zYRKlRsKjXZI4Lh-ZI4N0N1SEcqoKCnYl-RiUc5iG3vaKVsli0JgavpdFfudTeHB7ReXBISPMeSeVWnV-Y0Dcojb_Lg22h9PUJJK8JYoRQC7P42fPFhmB-cGWRAFLIA3Oh26bPEqzpEVD9UyMb2aIWVOY-iNU-x49dqBd6wn-ExOu07lbCVDvLM6TGAcVRssuTxWUHXK3DG1fhmhBL8BCpUGU11dxBmmqJYgZPF81FEYfCRXyU1fxInhaYkGDA8jY6OAabQXp7qLTc7Ea37YvdPu-In1lfi8W7Coo1vsEQfVG_WNziQNudVf_zYYmwGuPXiHcBIm3brvSuH7SeO9jsWfJ6lisv7aquShijYvSNq5h6ntdA7FO4DwQyyuGpyBHUlaETwKUJlFNCKTrhe0WWS3UkZBi7ABhrI8ubFOndaZS7rkp-qo5Byvj85eJKh_5EBXVeeap3GJVxti9lHbhE5_S3BfaoZWSg=
2 changes: 1 addition & 1 deletion hyperdrive/Algotrader.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def __init__(self, load=False):

self.broker = Robinhood()

if load is True:
if load:
self.broker.load_portfolio()


Expand Down
2 changes: 1 addition & 1 deletion hyperdrive/Broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def get_hists(self, symbols, span='year', interval='day', save=False):
df['begins_at'] = pd.to_datetime(df['begins_at']).apply(
lambda x: x.tz_localize(None))
# df = df.sort_values('begins_at')
if save is True:
if save:
self.writer.save_csv('data/data.csv', df)
return df

Expand Down
5 changes: 5 additions & 0 deletions hyperdrive/Calculus.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ def smooth(self, series, window, order):
order
)

def get_difference(self, old: set, new: set) -> tuple[set, set]:
minus = old.difference(new)
plus = new.difference(old)
return minus, plus

def derive(self, y, x=np.array([0, 1])):
if isinstance(x, pd.Series):
x = x.to_numpy()
Expand Down
5 changes: 3 additions & 2 deletions hyperdrive/DataSource.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from polygon import RESTClient, exceptions
from dotenv import load_dotenv, find_dotenv
from FileOps import FileReader, FileWriter
from Calculus import Calculator
from TimeMachine import TimeTraveller
from Constants import PathFinder
import Constants as C
Expand All @@ -27,6 +28,7 @@ def __init__(self):
self.reader = FileReader()
self.finder = PathFinder()
self.traveller = TimeTraveller()
self.calculator = Calculator()
self.provider = 'polygon'

def get_indexer(self, s1, s2):
Expand Down Expand Up @@ -419,8 +421,7 @@ def save_ndx(self, **kwargs):
before = set(self.standardize_ndx(saved)[C.SYMBOL])
after = set(self.get_latest_ndx(**kwargs)[C.SYMBOL])
today = datetime.now().strftime(C.DATE_FMT)
minus = before.difference(after)
plus = after.difference(before)
minus, plus = self.calculator.get_difference(before, after)
union = list(minus.union(plus))
to_append = pd.DataFrame({
C.TIME: [today] * len(union),
Expand Down
57 changes: 46 additions & 11 deletions hyperdrive/Exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@
import hashlib
import requests
import urllib.parse
from time import sleep
from binance import Client
from typing import Iterable, Union, Optional
from binance.helpers import round_step_size
from dotenv import load_dotenv, find_dotenv
import Constants as C
load_dotenv(find_dotenv('config.env'))


class CEX:
def create_pair(self, base, quote):
def create_pair(self, base: str, quote: str) -> str:
return f'{base}{quote}'


class AlpacaEx(CEX):
def __init__(
self,
token=os.environ.get('ALPACA'),
secret=os.environ.get('ALPACA_SECRET'),
paper=False
):
token: Optional[str] = os.environ.get('ALPACA'),
secret: Optional[str] = os.environ.get('ALPACA_SECRET'),
paper: bool = False
) -> None:
super().__init__()
self.base = (f'https://{"paper-" if paper or C.TEST else ""}'
'api.alpaca.markets')
Expand All @@ -35,7 +37,35 @@ def __init__(
if not (self.token and self.secret):
raise Exception('missing Alpaca credentials')

def make_request(self, method, route, payload={}):
def fill_orders(
self,
symbols: Iterable[str],
func: callable,
**kwargs: dict[str, any]
) -> list[dict[str, any]]:
pending_orders = set()
completed_orders = []
for symbol in symbols:
order = func(symbol, **kwargs)
if order['status'] == 'filled':
completed_orders.append(order)
else:
pending_orders.add(order['id'])
while pending_orders:
for id in list(pending_orders):
order = self.get_order(id)
if order['status'] == 'filled':
completed_orders.append(order)
pending_orders.discard(id)
sleep(1)
return completed_orders

def make_request(
self,
method: str,
route: str,
payload: Optional[dict[str, any]] = {}
) -> any:
parts = [self.base, self.version, route]
url = '/'.join(parts)
headers = {
Expand All @@ -49,19 +79,24 @@ def make_request(self, method, route, payload={}):
else:
raise Exception(response.text)

def get_positions(self):
def get_positions(self) -> any:
return self.make_request('GET', 'positions')

def close_position(self, symbol):
def close_position(self, symbol: str) -> any:
return self.make_request('DELETE', f'positions/{symbol}')

def get_order(self, id):
def get_order(self, id: str) -> any:
return self.make_request('GET', f'orders/{id}')

def get_account(self):
def get_account(self) -> any:
return self.make_request('GET', 'account')

def create_order(self, symbol, side, notional):
def create_order(
self,
symbol: str,
side: str,
notional: Union[int, float, str]
) -> any:
payload = {
'symbol': symbol,
'side': side.lower(),
Expand Down
7 changes: 3 additions & 4 deletions hyperdrive/History.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from sklearn.metrics import classification_report
from imblearn.over_sampling import SMOTE
from Calculus import Calculator
from collections.abc import Callable
import Constants as C


Expand All @@ -44,7 +43,7 @@ def from_signals(self, close, signals, init_cash=1000, fee=0):
def optimize_portfolio(
self,
close: pd.DataFrame,
indicator: Callable,
indicator: callable,
top_n: int,
period: str,
init_cash: float,
Expand All @@ -65,15 +64,15 @@ def optimize_portfolio(
if prev_period != curr_period:
# Rank symbols by indicator and select top_n
top_symbols = set(signals.loc[day].nlargest(top_n).index)
minus, plus = self.calc.get_difference(
prev_symbols, top_symbols)
# Sell old positions for the top symbols
minus = prev_symbols.difference(top_symbols)
for symbol in minus:
size = holdings[symbol]
positions.loc[day, symbol] = - size
holdings["cash"] += close.loc[day][symbol] * size
del holdings[symbol]
# Buy new positions for the top symbols
plus = top_symbols.difference(prev_symbols)
notional = holdings["cash"] / len(plus)
for symbol in plus:
size = notional / close.loc[day][symbol]
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ pynisher == 0.6.4
numpy == 1.23.5
beautifulsoup4 == 4.12.3
lxml == 5.3.0
selenium
plotly == 5.24.1
selenium
1 change: 1 addition & 0 deletions scripts/execute_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
num_unique_signals = len(set(last_two_signals))
signal = last_two_signals[-1]
should_order = num_unique_signals > 1
should_order = False # disable trading

if should_order:
side = C.BUY if signal else C.SELL
Expand Down
11 changes: 11 additions & 0 deletions test/test_Exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ def test_init(self):
assert hasattr(alpc, 'token')
assert hasattr(alpc, 'secret')

def test_fill_orders(self):
positions = alpc.get_positions()
if any([position['symbol'] == 'LTC/USD' for position in positions]):
orders = alpc.fill_orders(['LTC/USD'], alpc.close_position)
else:
orders = alpc.fill_orders(
['LTC/USD'], alpc.create_order, side='buy', notional=10)

for order in orders:
assert 'id' in order

def test_make_request(self):
acct = alpc.make_request('GET', 'account')
assert acct['status'] == 'ACTIVE'
Expand Down

0 comments on commit d5fc942

Please sign in to comment.