diff --git a/encrypted/optimize_portfolio.py.encrypted b/encrypted/optimize_portfolio.py.encrypted index 730a133..0b79ea7 100644 --- a/encrypted/optimize_portfolio.py.encrypted +++ b/encrypted/optimize_portfolio.py.encrypted @@ -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= \ No newline at end of file +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= \ No newline at end of file diff --git a/hyperdrive/Algotrader.py b/hyperdrive/Algotrader.py index 1f08a44..66e1efd 100755 --- a/hyperdrive/Algotrader.py +++ b/hyperdrive/Algotrader.py @@ -8,7 +8,7 @@ def __init__(self, load=False): self.broker = Robinhood() - if load is True: + if load: self.broker.load_portfolio() diff --git a/hyperdrive/Broker.py b/hyperdrive/Broker.py index 30788ed..c677381 100755 --- a/hyperdrive/Broker.py +++ b/hyperdrive/Broker.py @@ -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 diff --git a/hyperdrive/Calculus.py b/hyperdrive/Calculus.py index 6425552..bcb8157 100755 --- a/hyperdrive/Calculus.py +++ b/hyperdrive/Calculus.py @@ -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() diff --git a/hyperdrive/DataSource.py b/hyperdrive/DataSource.py index a5529c0..a673294 100755 --- a/hyperdrive/DataSource.py +++ b/hyperdrive/DataSource.py @@ -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 @@ -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): @@ -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), diff --git a/hyperdrive/Exchange.py b/hyperdrive/Exchange.py index 7abce16..fb56739 100755 --- a/hyperdrive/Exchange.py +++ b/hyperdrive/Exchange.py @@ -5,7 +5,9 @@ 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 @@ -13,17 +15,17 @@ 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') @@ -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 = { @@ -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(), diff --git a/hyperdrive/History.py b/hyperdrive/History.py index b779be0..c35fd81 100755 --- a/hyperdrive/History.py +++ b/hyperdrive/History.py @@ -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 @@ -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, @@ -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] diff --git a/requirements.txt b/requirements.txt index 425578d..6835ec4 100755 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,5 @@ pynisher == 0.6.4 numpy == 1.23.5 beautifulsoup4 == 4.12.3 lxml == 5.3.0 -selenium \ No newline at end of file +plotly == 5.24.1 +selenium diff --git a/scripts/execute_order.py b/scripts/execute_order.py index 9e1233b..1fd2dbb 100755 --- a/scripts/execute_order.py +++ b/scripts/execute_order.py @@ -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 diff --git a/test/test_Exchange.py b/test/test_Exchange.py index 4d7b2e1..d25b023 100755 --- a/test/test_Exchange.py +++ b/test/test_Exchange.py @@ -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'