From 4316d123b3c1611ccc9ee7c9503eb22a29047da6 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 7 Nov 2021 16:37:20 -0800 Subject: [PATCH 01/20] removed reference to BaseLogger --- harvest/storage/__init__.py | 2 -- harvest/trader/tester.py | 1 - harvest/trader/trader.py | 2 -- 3 files changed, 5 deletions(-) diff --git a/harvest/storage/__init__.py b/harvest/storage/__init__.py index fe657b5e..40f3f3c6 100644 --- a/harvest/storage/__init__.py +++ b/harvest/storage/__init__.py @@ -1,5 +1,3 @@ from harvest.storage.base_storage import BaseStorage from harvest.storage.csv_storage import CSVStorage from harvest.storage.pickle_storage import PickleStorage - -from harvest.storage.base_logger import BaseLogger diff --git a/harvest/trader/tester.py b/harvest/trader/tester.py index 4c16daea..4d7ec2ea 100644 --- a/harvest/trader/tester.py +++ b/harvest/trader/tester.py @@ -15,7 +15,6 @@ import harvest.trader.trader as trader from harvest.api.yahoo import YahooStreamer from harvest.api.paper import PaperBroker -from harvest.storage import BaseLogger from harvest.utils import * diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index 529341f8..ad516d0c 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -19,7 +19,6 @@ from harvest.api.dummy import DummyStreamer from harvest.api.paper import PaperBroker from harvest.storage import BaseStorage -from harvest.storage import BaseLogger from harvest.server import Server @@ -89,7 +88,6 @@ def _init_attributes(self): self.crypto_positions = [] # Local cache of current crypto positions. self.order_queue = [] # Queue of unfilled orders. - self.logger = BaseLogger() self.server = Server(self) # Initialize the web interface server self.timezone = tzlocal.get_localzone() From 831eb45726d5fd1df32b9cfd8de5f50673f5d747 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 7 Nov 2021 16:37:39 -0800 Subject: [PATCH 02/20] pdated kraken to match other brokers --- harvest/api/kraken.py | 189 +++++++++++++++++++++++++++--------------- 1 file changed, 121 insertions(+), 68 deletions(-) diff --git a/harvest/api/kraken.py b/harvest/api/kraken.py index a6a8cb91..6d4283c6 100644 --- a/harvest/api/kraken.py +++ b/harvest/api/kraken.py @@ -17,11 +17,10 @@ class Kraken(API): interval_list = [ Interval.MIN_1, Interval.MIN_5, - Interval.MIN_15, - Interval.MIN_30, Interval.HR_1, - Interval.DAY_1, + Interval.DAY_1 ] + crypto_ticker_to_kraken_names = { "BTC": "XXBT", "ETH": "XETH", @@ -113,19 +112,22 @@ class Kraken(API): "OXT": "OXT", } + kraken_names_to_crypto_ticker = {v: k for k, v in crypto_ticker_to_kraken_names.items()} + def __init__(self, path: str = None): super().__init__(path) self.api = krakenex.API(self.config["api_key"], self.config["secret_key"]) - def setup(self, watch: List[str], interval: str, trader=None, trader_main=None): + def setup(self, interval: Dict, trader=None, trader_main=None): + super().setup(interval, trader, trader_main) self.watch_crypto = [] - if is_crypto(s): - self.watch_crypto.append(s) - else: - debugger.error("Kraken does not support stocks.") + for sym in interval: + if is_crypto(sym): + self.watch_crypto.append(interval[sym]["interval"]) + else: + debugger.warning(f"Kraken does not support stocks. Ignoring {sym}.") self.option_cache = {} - super().setup(watch, interval, interval, trader, trader_main) def exit(self): self.option_cache = {} @@ -139,7 +141,7 @@ def main(self): @API._exception_handler def fetch_latest_crypto_price(self): dfs = {} - for symbol in self.watch_cryptos: + for symbol in self.watch_crypto: dfs[symbol] = self.fetch_price_history( symbol, self.interval, now() - dt.timedelta(days=7), now() ).iloc[[0]] @@ -151,7 +153,7 @@ def fetch_latest_crypto_price(self): def fetch_price_history( self, symbol: str, - interval: str, + interval: Interval, start: dt.datetime = None, end: dt.datetime = None, ): @@ -175,17 +177,16 @@ def fetch_price_history( f"Interval {interval} not in interval list. Possible options are: {self.interval_list}" ) val, unit = expand_interval(interval) - return self.get_data_from_kraken(symbol, val, unit, start, end) + df = self.get_data_from_kraken(symbol, val, unit, start, end) + + return df - @API._exception_handler def fetch_chain_info(self, symbol: str): raise NotImplementedError("Kraken does not support options.") - @API._exception_handler def fetch_chain_data(self, symbol: str, date: dt.datetime): raise NotImplementedError("Kraken does not support options.") - @API._exception_handler def fetch_option_market_data(self, occ_symbol: str): raise NotImplementedError("Kraken does not support options.") @@ -203,51 +204,93 @@ def fetch_option_positions(self): @API._exception_handler def fetch_crypto_positions(self): - return self.get_result(self.api.query_private("OpenOrders")) + positions = self.get_result(self.api.query_private("OpenPositions")) + def fmt(crypto: Dict[str, Any]): + # Remove the currency + symbol = crypto["pair"][:-4] + # Convert from kraken name to crypto currency ticker + symbol = kraken_name_to_crypto_ticker.get(symbol) + return { + "symbol": "@" + symbol, + "avg_price": float(crypto["cost"]) / float(crypto["vol"]), + "quantity": float(crypto["vol"]), + "kraken": crypto + } + + return [ + fmt(pos) + for pos in positions + ] + - @API._exception_handler def update_option_positions(self, positions: List[Any]): - raise NotImplementedError("Kraken does not support options.") + debugger.error("Kraken does not support options. Doing nothing.") @API._exception_handler def fetch_account(self): - return self.get_result(self.api.query_private("Balance")) + account = self.get_result(self.api.query_private("Balance")) + if account is None: + equity = 0 + cash = 0 + else: + equity = sum(float(v) for k, v in account.items() if k != "ZUSD") + cash = account.get("ZUSD", 0) + return { + "equity": equity, + "cash": cash, + "buying_power": equity + cash, + "multiplier": 1, + "kraken": account + } - @API._exception_handler def fetch_stock_order_status(self, order_id: str): return NotImplementedError("Kraken does not support stocks.") - @API._exception_handler - def fetch_option_order_status(self, id): + def fetch_option_order_status(self, order_id: str): raise Exception("Kraken does not support options.") @API._exception_handler - def fetch_crypto_order_status(self, id: str): - closed_orders = self.get_result(self.api.query_private("ClosedOrders")) - orders = closed_orders["closed"] + self.fetch_order_queue() - if id in orders.keys(): - return orders.get(id) - raise Exception(f"{id} not found in your orders.") + def fetch_crypto_order_status(self, order_id: str): + order = self.api.query_private("QueryOrders", {"txid": order_id}) + symbol = kraken_names_to_crypto_ticker.get(crypto["descr"]["pair"][:-4]) + return { + "type": "CRYPTO", + "symbol": "@" + symbol, + "id": crypto.key(), + "quantity": float(crypto["vol"]), + "filled_quantity": float(crypto["vol_exec"]), + "side": crypto["descr"]["type"], + "time_in_force": None, + "status": crypto["status"], + "kraken": crypto + } # --------------- Methods for Trading --------------- # @API._exception_handler def fetch_order_queue(self): open_orders = self.get_result(self.api.query_private("OpenOrders")) - return open_orders["open"] - - def order_stock_limit( - self, - symbol: str, - quantity: float, - limit_price: float, - order_type: str, - time_in_force: str, - order_id: str = None, - ): - raise NotImplementedError("Kraken does not support stocks.") - - def order_crypto_limit( + open_orders = open_orders["open"] + + def fmt(crypto: Dict[str, Any]): + symbol = kraken_names_to_crypto_ticker.get(crypto["descr"]["pair"][:-4]) + return { + "type": "CRYPTO", + "symbol": "@" + symbol, + "id": crypto.key(), + "quantity": float(crypto["vol"]), + "filled_quantity": float(crypto["vol_exec"]), + "side": crypto["descr"]["type"], + "time_in_force": None, + "status": crypto["status"], + "kraken": crypto + } + + return [ + fmt(order) for order in open_orders + ] + + def order_limit( self, side: str, symbol: str, @@ -256,10 +299,12 @@ def order_crypto_limit( in_force: str = "gtc", extended: bool = False, ): + if is_crypto(symbol): + symbol = ticker_to_kraken(symbol) + else: + raise Exception("Kraken does not support stocks.") - symbol = self.ticker_to_kraken(symbol) - - return self.get_result( + order = self.get_result( self.api.query_private( "AddOrder", { @@ -271,6 +316,13 @@ def order_crypto_limit( ) ) + return { + "type": "CRYPTO", + "id": order["txid"], + "symbol": symbol, + "kraken": order + } + def order_option_limit( self, side: str, @@ -336,6 +388,30 @@ def _format_df(self, df: pd.DataFrame, symbol: str): return df.dropna() + def ticker_to_kraken(self, ticker: str): + if not is_crypto(ticker): + raise Exception("Kraken does not support stocks.") + + if ticker[1:] in self.crypto_ticker_to_kraken_names: + # Currently Harvest supports trades for USD and not other currencies. + kraken_ticker = self.crypto_ticker_to_kraken_names.get(ticker[1:]) + "ZUSD" + asset_pairs = self.get_result(self.api.query_public("AssetPairs")).keys() + if kraken_ticker in asset_pairs: + return kraken_ticker + else: + raise Exception(f"{kraken_ticker} is not a valid asset pair.") + else: + raise Exception(f"Kraken does not support ticker {ticker}.") + + def get_result(self, response: Dict[str, Any]): + """Given a kraken response from an endpoint, either raise an error if an + error exists or return the data in the results key. + """ + print(response) + if len(response["error"]) > 0: + raise Exception("\n".join(response["error"])) + return response.get("result", None) + def create_secret(self, path: str) -> bool: import harvest.wizard as wizard @@ -382,26 +458,3 @@ def create_secret(self, path: str) -> bool: ) return True - - def ticker_to_kraken(self, ticker: str): - if not is_crypto(ticker): - raise Exception("Kraken does not support stocks.") - - if ticker[1:] not in self.crypto_ticker_to_kraken_names: - raise Exception(f"Kraken does not support ticker {ticker}.") - - # Currently Harvest supports trades for USD and not other currencies. - kraken_ticker = self.crypto_ticker_to_kraken_names.get(ticker[1:]) + "USD" - asset_pairs = self.get_result(self.api.query_public("AssetPairs")).keys() - if kraken_ticker in asset_pairs: - return kraken_ticker - else: - raise Exception(f"{kraken_ticker} is not a valid asset pair.") - - def get_result(self, response: Dict[str, Any]): - """Given a kraken response from an endpoint, either raise an error if an - error exists or return the data in the results key. - """ - if len(response["error"]) > 0: - raise Exception("\n".join(response["error"])) - return response["result"] From cacaa2adc65532e01ea416f5543fbfef005ad038 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 7 Nov 2021 20:57:12 -0800 Subject: [PATCH 03/20] added monitoring for kraken --- examples/em_kraken.py | 99 +++++++++++++++++++++++++++++++ harvest/api/_base.py | 27 +++++---- harvest/api/kraken.py | 11 ++-- harvest/storage/csv_storage.py | 2 +- harvest/storage/pickle_storage.py | 2 +- harvest/utils.py | 1 + 6 files changed, 121 insertions(+), 21 deletions(-) create mode 100644 examples/em_kraken.py diff --git a/examples/em_kraken.py b/examples/em_kraken.py new file mode 100644 index 00000000..caf11ac6 --- /dev/null +++ b/examples/em_kraken.py @@ -0,0 +1,99 @@ +# Builtin imports +import logging +import datetime as dt + +# Harvest imports +from harvest.algo import BaseAlgo +from harvest.trader import LiveTrader +from harvest.api.kraken import Kraken +from harvest.storage.csv_storage import CSVStorage + +# Third-party imports +import pandas as pd +import matplotlib.pyplot as plt +import mplfinance as mpf + + +class EMAlgo(BaseAlgo): + def setup(self): + now = dt.datetime.now() + logging.info(f"EMAlgo.setup ran at: {now}") + + def init_ticker(ticker): + fig = mpf.figure() + ax1 = fig.add_subplot(2, 1, 1) + ax2 = fig.add_subplot(3, 1, 3) + + return { + ticker: { + "initial_price": None, "ohlc": pd.DataFrame(), + "fig": fig, + "ax1": ax1, + "ax2": ax2 + } + } + + self.tickers = {} + # self.tickers.update(init_ticker("@BTC")) + self.tickers.update(init_ticker("@DOGE")) + + def main(self): + now = dt.datetime.now() + logging.info(f"EMAlgo.main ran at: {now}") + + if now - now.replace(hour=0, minute=0, second=0, microsecond=0) <= dt.timedelta( + seconds=60 + ): + logger.info(f"It's a new day! Clearning OHLC caches!") + for ticker_value in self.tickers.values(): + ticker_value["ohlc"] = pd.DataFrame() + + for ticker, ticker_value in self.tickers.items(): + current_price = self.get_asset_price(ticker) + current_ohlc = self.get_asset_candle(ticker) + if ticker_value["initial_price"] is None: + ticker_value["initial_price"] = current_price + + if current_ohlc.empty: + logging.warn(f"{ticker}'s get_asset_candle_list returned an empty list.") + return + + ticker_value["ohlc"] = ticker_value["ohlc"].append(current_ohlc) + + self.process_ticker(ticker, ticker_value, current_price) + + def process_ticker(self, ticker, ticker_data, current_price): + initial_price = ticker_data["initial_price"] + ohlc = ticker_data["ohlc"] + + # Calculate the price change + delta_price = current_price - initial_price + + # Print stock info + logging.info(f"{ticker} current price: ${current_price}") + logging.info(f"{ticker} price change: ${delta_price}") + + # Update the OHLC graph + ticker_data['ax1'].clear() + ticker_data['ax2'].clear() + mpf.plot(ohlc, ax=ticker_data['ax1'], volume=ticker_data['ax2'], type="candle") + plt.pause(3) + + +if __name__ == "__main__": + # Store the OHLC data in a folder called `em_storage` with each file stored as a csv document + csv_storage = CSVStorage(save_dir="em_storage") + # Our streamer and broker will be Alpaca. My secret keys are stored in `alpaca_secret.yaml` + kraken = Kraken( + path="accounts/kraken-secret.yaml" + ) + em_algo = EMAlgo() + trader = LiveTrader(streamer=kraken, broker=kraken, storage=csv_storage, debug=True) + + # trader.set_symbol("@BTC") + trader.set_symbol("@DOGE") + trader.set_algo(em_algo) + mpf.show() + + # Update every minute + trader.start("1MIN", all_history=False) diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 7099cf51..dbe9a86a 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -212,19 +212,20 @@ def _exception_handler(func): """ def wrapper(*args, **kwargs): - tries = 3 - while tries > 0: - try: - return func(*args, **kwargs) - except Exception as e: - self = args[0] - debugger.error(f"Error: {e}") - traceback.print_exc() - debugger.error("Logging out and back in...") - args[0].refresh_cred() - tries -= 1 - debugger.error("Retrying...") - continue + return func(*args, **kwargs) + # tries = 3 + # while tries > 0: + # try: + # return func(*args, **kwargs) + # except Exception as e: + # self = args[0] + # debugger.error(f"Error: {e}") + # traceback.print_exc() + # debugger.error("Logging out and back in...") + # args[0].refresh_cred() + # tries -= 1 + # debugger.error("Retrying...") + # continue return wrapper diff --git a/harvest/api/kraken.py b/harvest/api/kraken.py index 6d4283c6..8c8a9ee8 100644 --- a/harvest/api/kraken.py +++ b/harvest/api/kraken.py @@ -22,7 +22,7 @@ class Kraken(API): ] crypto_ticker_to_kraken_names = { - "BTC": "XXBT", + "BTC": "XXBTZ", "ETH": "XETH", "ADA": "ADA", "USDT": "USDT", @@ -123,7 +123,7 @@ def setup(self, interval: Dict, trader=None, trader_main=None): self.watch_crypto = [] for sym in interval: if is_crypto(sym): - self.watch_crypto.append(interval[sym]["interval"]) + self.watch_crypto.append(sym) else: debugger.warning(f"Kraken does not support stocks. Ignoring {sym}.") @@ -143,8 +143,8 @@ def fetch_latest_crypto_price(self): dfs = {} for symbol in self.watch_crypto: dfs[symbol] = self.fetch_price_history( - symbol, self.interval, now() - dt.timedelta(days=7), now() - ).iloc[[0]] + symbol, self.interval[symbol]["interval"], now() - dt.timedelta(days=7), now() + ).iloc[[-1]] return dfs # -------------- Streamer methods -------------- # @@ -394,7 +394,7 @@ def ticker_to_kraken(self, ticker: str): if ticker[1:] in self.crypto_ticker_to_kraken_names: # Currently Harvest supports trades for USD and not other currencies. - kraken_ticker = self.crypto_ticker_to_kraken_names.get(ticker[1:]) + "ZUSD" + kraken_ticker = self.crypto_ticker_to_kraken_names.get(ticker[1:]) + "USD" asset_pairs = self.get_result(self.api.query_public("AssetPairs")).keys() if kraken_ticker in asset_pairs: return kraken_ticker @@ -407,7 +407,6 @@ def get_result(self, response: Dict[str, Any]): """Given a kraken response from an endpoint, either raise an error if an error exists or return the data in the results key. """ - print(response) if len(response["error"]) > 0: raise Exception("\n".join(response["error"])) return response.get("result", None) diff --git a/harvest/storage/csv_storage.py b/harvest/storage/csv_storage.py index 0a600acc..b03859e7 100644 --- a/harvest/storage/csv_storage.py +++ b/harvest/storage/csv_storage.py @@ -61,7 +61,7 @@ def store( if not data.empty: self.storage_lock.acquire() - self.storage[symbol][interval][symbol].to_csv( + self.storage_price[symbol][interval][symbol].to_csv( self.save_dir + f"/{symbol}@{interval_enum_to_string(interval)}.csv" ) self.storage_lock.release() diff --git a/harvest/storage/pickle_storage.py b/harvest/storage/pickle_storage.py index fb0a104d..5bf4462a 100644 --- a/harvest/storage/pickle_storage.py +++ b/harvest/storage/pickle_storage.py @@ -63,7 +63,7 @@ def store( if not data.empty and save_pickle: self.storage_lock.acquire() - self.storage[symbol][interval].to_pickle( + self.storage_price[symbol][interval].to_pickle( self.save_dir + f"/{symbol}@{interval_enum_to_string(interval)}.pickle" ) self.storage_lock.release() diff --git a/harvest/utils.py b/harvest/utils.py index f8742d29..43cdc546 100644 --- a/harvest/utils.py +++ b/harvest/utils.py @@ -246,6 +246,7 @@ def datetime_utc_to_local(date_time: dt.datetime, timezone: ZoneInfo) -> dt.date Converts a datetime object in UTC to local time, represented as a timezone naive datetime object. """ + date_time = date_time.to_pydatetime() new_tz = date_time.astimezone(timezone) return new_tz.replace(tzinfo=None) From f586b651f86dc492f74f172eb06e97b483d1d920 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 7 Nov 2021 20:57:38 -0800 Subject: [PATCH 04/20] linted --- harvest/algo.py | 7 +-- harvest/api/_base.py | 19 ++++--- harvest/api/kraken.py | 37 ++++++------- harvest/api/paper.py | 2 +- harvest/api/polygon.py | 4 +- harvest/api/robinhood.py | 8 +-- harvest/cli.py | 7 +-- harvest/storage/base_storage.py | 97 ++++++++++++++++++--------------- harvest/trader/trader.py | 63 ++++++++++----------- 9 files changed, 124 insertions(+), 120 deletions(-) diff --git a/harvest/algo.py b/harvest/algo.py index de12af96..719fcc73 100644 --- a/harvest/algo.py +++ b/harvest/algo.py @@ -141,7 +141,7 @@ def sell( debugger.debug(f"Algo SELL: {symbol}, {quantity}") return self.trader.sell(symbol, quantity, in_force, extended) - + def sell_all_options(self, symbol: str = None, in_force: str = "gtc"): """Sells all options of a stock @@ -164,7 +164,7 @@ def sell_all_options(self, symbol: str = None, in_force: str = "gtc"): debugger.debug(f"Algo SELL OPTION: {s}") quantity = self.get_asset_quantity(s) ret.append(self.trader.sell_option(s, quantity, in_force)) - + return ret # def buy_option(self, symbol: str, quantity: int = None, in_force: str = "gtc"): @@ -522,9 +522,8 @@ def get_asset_quantity(self, symbol: str = None) -> float: """ if symbol is None: symbol = self.watchlist[0] - - return self.trader.get_asset_quantity(symbol, exclude_pending_sell=True) + return self.trader.get_asset_quantity(symbol, exclude_pending_sell=True) def get_asset_cost(self, symbol: str = None) -> float: """Returns the average cost of a specified asset. diff --git a/harvest/api/_base.py b/harvest/api/_base.py index dbe9a86a..4e8555db 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -22,7 +22,7 @@ class API: Attributes :interval_list: A list of supported intervals. - :exchange: The market the API trades on. Ignored if the API is not a broker. + :exchange: The market the API trades on. Ignored if the API is not a broker. """ interval_list = [ @@ -307,10 +307,10 @@ def fetch_option_market_data(self, symbol: str): raise NotImplementedError( f"{type(self).__name__} does not support this streamer method: `fetch_option_market_data`." ) - + def fetch_market_hours(self, date: datetime.date): """ - Returns the market hours for a given day. + Returns the market hours for a given day. Hours are based on the exchange specified in the class's 'exchange' attribute. :returns: A dictionary with the following keys and values: @@ -597,7 +597,12 @@ def order_option_limit( # These do not need to be re-implemented in a subclass def buy( - self, symbol: str, quantity: int, limit_price: float, in_force: str = "gtc", extended: bool = False + self, + symbol: str, + quantity: int, + limit_price: float, + in_force: str = "gtc", + extended: bool = False, ): """ Buys the specified asset. @@ -654,7 +659,7 @@ def sell( :returns: The result of order_limit(). Returns None if there is an issue with the parameters. """ - + debugger.debug(f"{type(self).__name__} ordered a sell of {quantity} {symbol}") typ = symbol_type(symbol) @@ -708,8 +713,8 @@ def sell( # if total_price >= buy_power: # debugger.warning( - # "Not enough buying power.\n" + - # f"Total price ({price} * {quantity} * 1.05 = {limit_price*quantity}) exceeds buying power {buy_power}.\n" + + # "Not enough buying power.\n" + + # f"Total price ({price} * {quantity} * 1.05 = {limit_price*quantity}) exceeds buying power {buy_power}.\n" + # "Reduce purchase quantity or increase buying power." # ) diff --git a/harvest/api/kraken.py b/harvest/api/kraken.py index 8c8a9ee8..d050135f 100644 --- a/harvest/api/kraken.py +++ b/harvest/api/kraken.py @@ -14,12 +14,7 @@ class Kraken(API): - interval_list = [ - Interval.MIN_1, - Interval.MIN_5, - Interval.HR_1, - Interval.DAY_1 - ] + interval_list = [Interval.MIN_1, Interval.MIN_5, Interval.HR_1, Interval.DAY_1] crypto_ticker_to_kraken_names = { "BTC": "XXBTZ", @@ -112,7 +107,9 @@ class Kraken(API): "OXT": "OXT", } - kraken_names_to_crypto_ticker = {v: k for k, v in crypto_ticker_to_kraken_names.items()} + kraken_names_to_crypto_ticker = { + v: k for k, v in crypto_ticker_to_kraken_names.items() + } def __init__(self, path: str = None): super().__init__(path) @@ -143,7 +140,10 @@ def fetch_latest_crypto_price(self): dfs = {} for symbol in self.watch_crypto: dfs[symbol] = self.fetch_price_history( - symbol, self.interval[symbol]["interval"], now() - dt.timedelta(days=7), now() + symbol, + self.interval[symbol]["interval"], + now() - dt.timedelta(days=7), + now(), ).iloc[[-1]] return dfs @@ -205,6 +205,7 @@ def fetch_option_positions(self): @API._exception_handler def fetch_crypto_positions(self): positions = self.get_result(self.api.query_private("OpenPositions")) + def fmt(crypto: Dict[str, Any]): # Remove the currency symbol = crypto["pair"][:-4] @@ -214,14 +215,10 @@ def fmt(crypto: Dict[str, Any]): "symbol": "@" + symbol, "avg_price": float(crypto["cost"]) / float(crypto["vol"]), "quantity": float(crypto["vol"]), - "kraken": crypto + "kraken": crypto, } - return [ - fmt(pos) - for pos in positions - ] - + return [fmt(pos) for pos in positions] def update_option_positions(self, positions: List[Any]): debugger.error("Kraken does not support options. Doing nothing.") @@ -240,7 +237,7 @@ def fetch_account(self): "cash": cash, "buying_power": equity + cash, "multiplier": 1, - "kraken": account + "kraken": account, } def fetch_stock_order_status(self, order_id: str): @@ -262,7 +259,7 @@ def fetch_crypto_order_status(self, order_id: str): "side": crypto["descr"]["type"], "time_in_force": None, "status": crypto["status"], - "kraken": crypto + "kraken": crypto, } # --------------- Methods for Trading --------------- # @@ -283,12 +280,10 @@ def fmt(crypto: Dict[str, Any]): "side": crypto["descr"]["type"], "time_in_force": None, "status": crypto["status"], - "kraken": crypto + "kraken": crypto, } - return [ - fmt(order) for order in open_orders - ] + return [fmt(order) for order in open_orders] def order_limit( self, @@ -320,7 +315,7 @@ def order_limit( "type": "CRYPTO", "id": order["txid"], "symbol": symbol, - "kraken": order + "kraken": order, } def order_option_limit( diff --git a/harvest/api/paper.py b/harvest/api/paper.py index 4661b437..0d108c03 100644 --- a/harvest/api/paper.py +++ b/harvest/api/paper.py @@ -324,7 +324,7 @@ def order_crypto_limit( ): data = { "type": "CRYPTO", - "symbol": '@'+symbol, + "symbol": "@" + symbol, "quantity": quantity, "filled_qty": quantity, "limit_price": limit_price, diff --git a/harvest/api/polygon.py b/harvest/api/polygon.py index 717fed54..4809fb1d 100644 --- a/harvest/api/polygon.py +++ b/harvest/api/polygon.py @@ -47,7 +47,9 @@ def main(self): return for s in combo: - df = self.fetch_price_history(s, Interval.MIN_1, now() - dt.timedelta(days=1), now()).iloc[-1] + df = self.fetch_price_history( + s, Interval.MIN_1, now() - dt.timedelta(days=1), now() + ).iloc[-1] df_dict[s] = df debugger.debug(df) self.trader_main(df_dict) diff --git a/harvest/api/robinhood.py b/harvest/api/robinhood.py index f98ae041..9d409383 100644 --- a/harvest/api/robinhood.py +++ b/harvest/api/robinhood.py @@ -388,7 +388,7 @@ def fetch_option_order_status(self, id): "time_in_force": ret["time_in_force"], "status": ret["state"], "filled_time": filled_time, - "filled_price": filled_price + "filled_price": filled_price, } @API._exception_handler @@ -551,7 +551,7 @@ def order_crypto_limit( return { "type": "CRYPTO", "id": ret["id"], - "symbol": '@'+ symbol, + "symbol": "@" + symbol, } except: debugger.error("Error while placing order.\nReturned: {ret}", exc_info=True) @@ -630,9 +630,9 @@ def _format_df( df.columns = pd.MultiIndex.from_product([watch, df.columns]) return df.dropna() - + def _rh_datestr_to_datetime(self, date_str: str): - date_str = date_str[:-3]+date_str[-2:] + date_str = date_str[:-3] + date_str[-2:] return dt.datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%S.%f%z") def create_secret(self, path): diff --git a/harvest/cli.py b/harvest/cli.py index ce65a3e0..fa16c0d7 100644 --- a/harvest/cli.py +++ b/harvest/cli.py @@ -117,9 +117,8 @@ def raise_helper(): # Parser for visualing data visualize_parser = subparsers.add_parser("visualize") -visualize_parser.add_argument( - "path", help="path to harvest generated data file" -) +visualize_parser.add_argument("path", help="path to harvest generated data file") + def main(): """ @@ -183,6 +182,7 @@ def start(args: argparse.Namespace, test: bool = False): if not test: trader.start() + def visualize(args: argparse.Namespace): import re import pandas as pd @@ -218,7 +218,6 @@ def visualize(args: argparse.Namespace): mpf.plot(df, type="candle", volume=True, show_nontrading=True) - def _get_storage(storage: str): """ Returns the storage instance specified by the user. diff --git a/harvest/storage/base_storage.py b/harvest/storage/base_storage.py index 78f8cf1b..ec3b9362 100644 --- a/harvest/storage/base_storage.py +++ b/harvest/storage/base_storage.py @@ -43,6 +43,7 @@ as long as they implement the API properly. """ + class BaseStorage: """ A basic storage that is thread safe and stores data in memory. @@ -58,22 +59,22 @@ class BaseStorage: ] def __init__( - self, - price_storage_size: int = 200, - price_storage_limit: bool = True, - transaction_storage_size: int = 200, - transaction_storage_limit: bool = True, - performance_storage_size: int = 200, - performance_storage_limit: bool = True, - ): + self, + price_storage_size: int = 200, + price_storage_limit: bool = True, + transaction_storage_size: int = 200, + transaction_storage_limit: bool = True, + performance_storage_size: int = 200, + performance_storage_limit: bool = True, + ): """ - queue_size: The maximum number of data points to store for asset price history. + queue_size: The maximum number of data points to store for asset price history. This helps prevent the database from becoming infinitely large as time progresses. - limit_size: Whether to limit the size of price history to queue_size. + limit_size: Whether to limit the size of price history to queue_size. This may be set to False if the storage is being used for backtesting, in which case you would want to store as much data as possible. """ - self.storage_lock = Lock() # Lock + self.storage_lock = Lock() # Lock self.price_storage_size = price_storage_size self.price_storage_limit = price_storage_limit @@ -84,10 +85,17 @@ def __init__( # BaseStorage uses a python dictionary to store the data, # where key is asset symbol and value is a pandas dataframe. - self.storage_price = {} + self.storage_price = {} self.storage_transaction = pd.DataFrame( - columns=["timestamp", "algorithm_name", "symbol", "side", "quantity", "price"] + columns=[ + "timestamp", + "algorithm_name", + "symbol", + "side", + "quantity", + "price", + ] ) self.storage_performance = {} @@ -95,15 +103,13 @@ def __init__( self.storage_performance[interval] = pd.DataFrame( columns=["equity"], index=[] ) - + def setup(self, trader): """ - Sets up the storage + Sets up the storage """ self.trader = trader - - def store( self, symbol: str, interval: Interval, data: pd.DataFrame, remove_duplicate=True ) -> None: @@ -131,7 +137,9 @@ def store( intervals[interval], data, remove_duplicate=remove_duplicate ) if self.price_storage_limit: - intervals[interval] = intervals[interval][-self.price_storage_size:] + intervals[interval] = intervals[interval][ + -self.price_storage_size : + ] except: raise Exception("Append Failure, case not found!") else: @@ -150,13 +158,12 @@ def store( cur_len = len(self.storage_price[symbol][interval]) if self.price_storage_limit and cur_len > self.price_storage_size: # If we have more than N data points, remove the oldest data - self.storage_price[symbol][interval] = self.storage_price[symbol][interval].iloc[ - -self.price_storage_size : - ] + self.storage_price[symbol][interval] = self.storage_price[symbol][ + interval + ].iloc[-self.price_storage_size :] self.storage_lock.release() - def load( self, symbol: str, @@ -201,7 +208,7 @@ def load( if start is None and end is None: self.storage_lock.release() - return data + return data # If the start and end are not defined, then set them to the # beginning and end of the data. @@ -211,19 +218,19 @@ def load( end = data.index[-1] return data.loc[start:end] - + def store_transaction( - self, + self, timestamp: dt.datetime, algorithm_name: str, - symbol: str, + symbol: str, side: str, quantity: int, - price: float + price: float, ) -> None: self.storage_transaction.append( [timestamp, algorithm_name, symbol, side, quantity, price], - ignore_index=True + ignore_index=True, ) def reset(self, symbol: str, interval: Interval): @@ -234,7 +241,6 @@ def reset(self, symbol: str, interval: Interval): self.storage_price[symbol][interval] = pd.DataFrame() self.storage_lock.release() - def _append( self, current_data: pd.DataFrame, @@ -267,19 +273,21 @@ def aggregate( self.storage_lock.acquire() data = self.storage_price[symbol][base] self.storage_price[symbol][target] = self._append( - self.storage_price[symbol][target], aggregate_df(data, target), remove_duplicate + self.storage_price[symbol][target], + aggregate_df(data, target), + remove_duplicate, ) cur_len = len(self.storage_price[symbol][target]) if self.price_storage_limit and cur_len > self.price_storage_size: - self.storage_price[symbol][target] = self.storage_price[symbol][target].iloc[ - -self.price_storage_size : - ] + self.storage_price[symbol][target] = self.storage_price[symbol][ + target + ].iloc[-self.price_storage_size :] self.storage_lock.release() def init_performace_data(self, equity: float): for interval, days in self.performance_history_intervals: self.storage_performance[interval] = pd.DataFrame( - {'equity': [equity]}, index=[self.trader.timestamp] + {"equity": [equity]}, index=[self.trader.timestamp] ) def add_performance_data(self, equity: float): @@ -290,12 +298,12 @@ def add_performance_data(self, equity: float): It takes the current equity and adds it to each interval. - :param equity: Current equity of the account. + :param equity: Current equity of the account. """ cur_timestamp = self.trader.timestamp # Performance history range up until '3 MONTHS' have the - # same interval as the polling interval of the trader. + # same interval as the polling interval of the trader. for interval, days in self.performance_history_intervals[0:3]: df = self.storage_performance[interval] cutoff = cur_timestamp - dt.timedelta(days=days) @@ -309,24 +317,25 @@ def add_performance_data(self, equity: float): for interval, days in self.performance_history_intervals[3:5]: df = self.storage_performance[interval] if df.index[-1].date() == cur_timestamp.date(): - df = df.iloc[:-1] - df = df.append(pd.DataFrame({"equity": [equity]}, index=[cur_timestamp])) + df = df.iloc[:-1] + df = df.append( + pd.DataFrame({"equity": [equity]}, index=[cur_timestamp]) + ) else: - df = df.append(pd.DataFrame({"equity": [equity]}, index=[cur_timestamp])) + df = df.append( + pd.DataFrame({"equity": [equity]}, index=[cur_timestamp]) + ) cutoff = cur_timestamp - dt.timedelta(days=days) if df.index[0] < cutoff: df = df.loc[df.index >= cutoff] self.storage_performance[interval] = df - + df = self.storage_performance["ALL"] if df.index[-1].date() == cur_timestamp.date(): - df = df.iloc[:-1] + df = df.iloc[:-1] df = df.append(pd.DataFrame({"equity": [equity]}, index=[cur_timestamp])) self.storage_performance["ALL"] = df debugger.debug("Performance data added") for k in self.storage_performance: debugger.debug(f"{k}:\n {self.storage_performance[k]}") - - - diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index ad516d0c..e4ed5b21 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -46,9 +46,7 @@ def __init__(self, streamer=None, broker=None, storage=None, debug=False): self._set_streamer_broker(streamer, broker) # Initialize the storage - self.storage = ( - BaseStorage() if storage is None else storage - ) + self.storage = BaseStorage() if storage is None else storage self.storage.setup(self) self._init_attributes() @@ -272,7 +270,7 @@ def _storage_init(self, all_history: bool): start = None if all_history else now() - dt.timedelta(days=3) df = self.streamer.fetch_price_history(sym, inter, start) self.storage.store(sym, inter, df) - + # ================== Functions for main routine ===================== def main(self, df_dict): @@ -283,7 +281,7 @@ def main(self, df_dict): # Periodically refresh access tokens if self.timestamp.hour % 12 == 0 and self.timestamp.minute == 0: self.streamer.refresh_cred() - + self.storage.add_performance_data(self.account["equity"]) # Save the data locally @@ -351,14 +349,16 @@ def _update_order_queue(self): # TODO: handle cancelled orders if order["status"] == "filled": order_filled = True - debugger.debug(f"Order {order['id']} filled at {order['filled_time']} at {order['filled_price']}") + debugger.debug( + f"Order {order['id']} filled at {order['filled_time']} at {order['filled_price']}" + ) self.storage.store_transaction( order["filled_time"], "N/A", order["symbol"], order["side"], order["quantity"], - order["filled_price"] + order["filled_price"], ) else: new_order.append(order) @@ -433,24 +433,24 @@ def buy(self, symbol: str, quantity: int, in_force: str, extended: bool): if symbol_type(symbol) == "OPTION": price = self.streamer.fetch_option_market_data(symbol)["price"] else: - price = self.storage.load( - symbol, self.interval[symbol]["interval"] - )[symbol]["close"][-1] + price = self.storage.load(symbol, self.interval[symbol]["interval"])[ + symbol + ]["close"][-1] limit_price = mark_up(price) total_price = limit_price * quantity if total_price >= buy_power: debugger.error( - "Not enough buying power.\n" + - f"Total price ({price} * {quantity} * 1.05 = {limit_price*quantity}) exceeds buying power {buy_power}." + - "Reduce purchase quantity or increase buying power." + "Not enough buying power.\n" + + f"Total price ({price} * {quantity} * 1.05 = {limit_price*quantity}) exceeds buying power {buy_power}." + + "Reduce purchase quantity or increase buying power." ) return None - + # TODO? Perform other checks ret = self.broker.buy(symbol, quantity, limit_price, in_force, extended) - + if ret is None: debugger.debug("BUY failed") return None @@ -463,9 +463,11 @@ def sell(self, symbol: str, quantity: int, in_force: str, extended: bool): # Check how many of the given asset we currently own owned_qty = self.get_asset_quantity(symbol, exclude_pending_sell=True) if quantity > owned_qty: - debugger.debug("SELL failed: More quantities are being sold than currently owned.") + debugger.debug( + "SELL failed: More quantities are being sold than currently owned." + ) return None - + if symbol_type(symbol) == "OPTION": price = self.trader.streamer.fetch_option_market_data(symbol)["price"] else: @@ -482,12 +484,11 @@ def sell(self, symbol: str, quantity: int, in_force: str, extended: bool): self.order_queue.append(ret) debugger.debug(f"SELL: {self.timestamp}, {symbol}, {quantity}") return ret - + # ================ Helper Functions ====================== def get_asset_quantity( - self, symbol: str = None, - include_pending_buy = False, - exclude_pending_sell = False ) -> float: + self, symbol: str = None, include_pending_buy=False, exclude_pending_sell=False + ) -> float: """Returns the quantity owned of a specified asset. :param str? symbol: Symbol of asset. defaults to first symbol in watchlist @@ -496,40 +497,34 @@ def get_asset_quantity( """ if symbol is None: symbol = self.watchlist_global[0] - + if typ := symbol_type(symbol) == "OPTION": owned_qty = sum( - p["quantity"] - for p in self.option_positions - if p["symbol"] == symbol + p["quantity"] for p in self.option_positions if p["symbol"] == symbol ) elif typ == "CRYPTO": owned_qty = sum( - p["quantity"] - for p in self.crypto_positions - if p["symbol"] == symbol + p["quantity"] for p in self.crypto_positions if p["symbol"] == symbol ) else: owned_qty = sum( - p["quantity"] - for p in self.stock_positions - if p["symbol"] == symbol + p["quantity"] for p in self.stock_positions if p["symbol"] == symbol ) - + if include_pending_buy: owned_qty += sum( o["quantity"] for o in self.order_queue if o["symbol"] == symbol and o["side"] == "buy" ) - + if exclude_pending_sell: owned_qty -= sum( o["quantity"] for o in self.order_queue if o["symbol"] == symbol and o["side"] == "sell" ) - + return owned_qty # def buy_option(self, symbol: str, quantity: int, in_force: str): From eac5b5c5a0d5e927b0287be7e176fb2315fc4ce3 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 7 Nov 2021 21:17:07 -0800 Subject: [PATCH 05/20] uncommented code --- harvest/api/_base.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 4e8555db..3c3fd92d 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -212,20 +212,19 @@ def _exception_handler(func): """ def wrapper(*args, **kwargs): - return func(*args, **kwargs) - # tries = 3 - # while tries > 0: - # try: - # return func(*args, **kwargs) - # except Exception as e: - # self = args[0] - # debugger.error(f"Error: {e}") - # traceback.print_exc() - # debugger.error("Logging out and back in...") - # args[0].refresh_cred() - # tries -= 1 - # debugger.error("Retrying...") - # continue + tries = 3 + while tries > 0: + try: + return func(*args, **kwargs) + except Exception as e: + self = args[0] + debugger.error(f"Error: {e}") + traceback.print_exc() + debugger.error("Logging out and back in...") + args[0].refresh_cred() + tries -= 1 + debugger.error("Retrying...") + continue return wrapper From 35662585700c97639108e1192f4d2545dae9ff33 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Mon, 8 Nov 2021 19:47:51 -0800 Subject: [PATCH 06/20] fixed lock issue --- harvest/storage/base_storage.py | 4 ++++ tests/test_storage.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/harvest/storage/base_storage.py b/harvest/storage/base_storage.py index ec3b9362..2e632b54 100644 --- a/harvest/storage/base_storage.py +++ b/harvest/storage/base_storage.py @@ -141,6 +141,7 @@ def store( -self.price_storage_size : ] except: + self.storage_lock.release() raise Exception("Append Failure, case not found!") else: # Add the data as a new interval @@ -197,7 +198,9 @@ def load( ] intervals.sort(key=lambda interval_timedelta: interval_timedelta[1]) for interval_timedelta in intervals: + self.storage_lock.release() data = self.load(symbol, interval_timedelta[0], start, end) + self.storage_lock.acquire() if data is not None: self.storage_lock.release() return data @@ -217,6 +220,7 @@ def load( if end is None: end = data.index[-1] + self.storage_lock.release() return data.loc[start:end] def store_transaction( diff --git a/tests/test_storage.py b/tests/test_storage.py index bd2a7e20..4347be7a 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -11,7 +11,7 @@ class TestBaseStorage(unittest.TestCase): def test_create_storage(self): storage = BaseStorage() - self.assertEqual(storage.storage, {}) + self.assertEqual(storage.storage_price, {}) def test_simple_store(self): storage = BaseStorage() @@ -19,8 +19,8 @@ def test_simple_store(self): storage.store("A", Interval.MIN_1, data.copy(True)) self.assertTrue(not pd.isna(data.iloc[0]["A"]["low"])) - self.assertEqual(list(storage.storage.keys()), ["A"]) - self.assertEqual(list(storage.storage["A"].keys()), [Interval.MIN_1]) + self.assertEqual(list(storage.storage_price.keys()), ["A"]) + self.assertEqual(list(storage.storage_price["A"].keys()), [Interval.MIN_1]) def test_simple_load(self): storage = BaseStorage() From 7c3fa0bf019e56e93e4bc1b0fc290db8acefe86e Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Wed, 10 Nov 2021 20:31:00 -0800 Subject: [PATCH 07/20] removed outdated documents --- docs/harvest_architecture.png | Bin 72302 -> 0 bytes docs/harvest_start_flow.png | Bin 83731 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/harvest_architecture.png delete mode 100644 docs/harvest_start_flow.png diff --git a/docs/harvest_architecture.png b/docs/harvest_architecture.png deleted file mode 100644 index 239acb3d03831c2a0c5550c038ec57b4ccb09f9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72302 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 tX^ Date: Wed, 10 Nov 2021 20:31:57 -0800 Subject: [PATCH 08/20] removed the need for trader in the brokers --- harvest/api/_base.py | 54 +++++++++++++++++++++------------------- harvest/api/alpaca.py | 4 +-- harvest/api/dummy.py | 2 +- harvest/api/kraken.py | 4 +-- harvest/api/paper.py | 4 +-- harvest/api/polygon.py | 4 +-- harvest/api/robinhood.py | 4 +-- harvest/api/webull.py | 4 +-- harvest/api/yahoo.py | 7 +++--- 9 files changed, 46 insertions(+), 41 deletions(-) diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 3c3fd92d..4e27585d 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -53,11 +53,6 @@ def __init__(self, path: str = None): :path: path to the YAML file containing credentials to communicate with the API. If not specified, defaults to './secret.yaml' """ - self.trader = ( - None # Allows broker to handle the case when runs without a trader - ) - - self.run_count = 0 if path is None: path = "./secret.yaml" @@ -69,7 +64,6 @@ def __init__(self, path: str = None): with open(path, "r") as stream: self.config = yaml.safe_load(stream) - self.run_count = 0 self.timestamp = now() def create_secret(self, path: str): @@ -85,14 +79,15 @@ def refresh_cred(self): """ debugger.info(f"Refreshing credentials for {type(self).__name__}.") - def setup(self, interval: Dict, trader=None, trader_main=None) -> None: + def setup(self, interval: Dict, trader_main=None) -> None: """ This function is called right before the algorithm begins, and initializes several runtime parameters like the symbols to watch and what interval data is needed. + + :trader_main: A callback function to the trader which will pass the data to the algorithms. """ - self.trader = trader self.trader_main = trader_main min_interval = None @@ -187,7 +182,7 @@ def main(self): latest = self.fetch_price_history( sym, inter, n - interval_to_timedelta(inter) * 2, n ) - debugger.debug(f"Price fetch returned: \n{latest}") + debugger.debug(f"{sym} price fetch returned: {latest}") if latest is None or latest.empty: continue df_dict[sym] = latest.iloc[-1] @@ -229,13 +224,18 @@ def wrapper(*args, **kwargs): return wrapper def _run_once(func): - """ """ + """ + Wrapper to only allows wrapped functions to be run once. + :func: Function to wrap. + :returns: The return of the inputted function if it has not been run before and None otherwise. + """ + + ran = False def wrapper(*args, **kwargs): - self = args[0] - if self.run_count == 0: - self.run_count += 1 - return func(args, kwargs) + if not ran: + ran = True + return func(*args, **kwargs) return None return wrapper @@ -248,10 +248,11 @@ def fetch_price_history( interval: Interval, start: dt.datetime = None, end: dt.datetime = None, - ): + ) -> pd.DataFrame: """ Fetches historical price data for the specified asset and period - using the API. + using the API. The first row is the earliest entry and the last + row is the latest entry. :param symbol: The stock/crypto to get data for. :param interval: The interval of requested historical data. @@ -822,8 +823,8 @@ def __init__(self, path: str = None): self.block_queue = {} self.first = True - def setup(self, interval: Dict, trader=None, trader_main=None) -> None: - super().setup(interval, trader, trader_main) + def setup(self, interval: Dict, trader_main=None) -> None: + super().setup(interval, trader_main) self.blocker = {} def start(self): @@ -866,7 +867,7 @@ def main(self, df_dict): # If there are data that has not been received, start a timer if self.first: - timer = threading.Thread(target=self.timeout, daemon=True) + timer = threading.Thread(self.timeout, daemon=True) timer.start() self.all_recv = False self.first = False @@ -883,14 +884,17 @@ def timeout(self): self.flush() def flush(self): - # For missing data, repeat the existing one + # For missing data, return a OHLC with all zeroes. self.block_lock.acquire() for n in self.needed: - data = ( - self.trader.storage.load(n, self.interval[n]["interval"]) - .iloc[[-1]] - .copy() - ) + data = pd.DataFrame({ + 'open': 0, + 'high': 0, + 'low': 0, + 'close': 0, + 'volume': 0 + }) + data.index = [self.timestamp] self.block_queue[n] = data self.block_lock.release() diff --git a/harvest/api/alpaca.py b/harvest/api/alpaca.py index c30f9b29..f1a52f24 100644 --- a/harvest/api/alpaca.py +++ b/harvest/api/alpaca.py @@ -76,8 +76,8 @@ async def update_data(self, bar): else: self.data_lock.release() - def setup(self, interval: Dict, trader=None, trader_main=None): - super().setup(interval, trader, trader_main) + def setup(self, interval: Dict, trader_main=None): + super().setup(interval, trader_main) self.watch_stock = [] self.watch_crypto = [] diff --git a/harvest/api/dummy.py b/harvest/api/dummy.py index 87083230..4f0fc8dc 100644 --- a/harvest/api/dummy.py +++ b/harvest/api/dummy.py @@ -35,7 +35,7 @@ def __init__( now: dt.datetime = default_now, realistic_times: bool = False, ): - self.trader = None + self.trader_main = None self.realistic_times = realistic_times diff --git a/harvest/api/kraken.py b/harvest/api/kraken.py index d050135f..4b01cba0 100644 --- a/harvest/api/kraken.py +++ b/harvest/api/kraken.py @@ -115,8 +115,8 @@ def __init__(self, path: str = None): super().__init__(path) self.api = krakenex.API(self.config["api_key"], self.config["secret_key"]) - def setup(self, interval: Dict, trader=None, trader_main=None): - super().setup(interval, trader, trader_main) + def setup(self, interval: Dict, trader_main=None): + super().setup(interval, trader_main) self.watch_crypto = [] for sym in interval: if is_crypto(sym): diff --git a/harvest/api/paper.py b/harvest/api/paper.py index 0d108c03..c68e1d19 100644 --- a/harvest/api/paper.py +++ b/harvest/api/paper.py @@ -64,8 +64,8 @@ def __init__(self, account_path: str = None, commission_fee=0): for crypto in account["cryptos"]: self.cryptos.append(crypto) - def setup(self, interval, trader=None, trader_main=None): - super().setup(interval, trader, trader_main) + def setup(self, interval, trader_main=None): + super().setup(interval, trader_main) # -------------- Streamer methods -------------- # diff --git a/harvest/api/polygon.py b/harvest/api/polygon.py index 4809fb1d..6de3b270 100644 --- a/harvest/api/polygon.py +++ b/harvest/api/polygon.py @@ -21,7 +21,7 @@ def __init__(self, path: str = None, is_basic_account: bool = False): super().__init__(path) self.basic = is_basic_account - def setup(self, interval, trader=None, trader_main=None): + def setup(self, interval, trader_main=None): self.watch_stock = [] self.watch_crypto = [] @@ -32,7 +32,7 @@ def setup(self, interval, trader=None, trader_main=None): self.watch_stock.append(sym) self.option_cache = {} - super().setup(interval, trader, trader_main) + super().setup(interval, trader_main) def exit(self): self.option_cache = {} diff --git a/harvest/api/robinhood.py b/harvest/api/robinhood.py index 9d409383..6cd63011 100644 --- a/harvest/api/robinhood.py +++ b/harvest/api/robinhood.py @@ -42,9 +42,9 @@ def refresh_cred(self): debugger.debug("Logged into Robinhood...") # @API._run_once - def setup(self, interval, trader=None, trader_main=None): + def setup(self, interval trader_main=None): - super().setup(interval, trader, trader_main) + super().setup(interval, trader_main) # Robinhood only supports 15SEC, 1MIN interval for crypto for sym in interval: diff --git a/harvest/api/webull.py b/harvest/api/webull.py index 323f7700..1110e980 100644 --- a/harvest/api/webull.py +++ b/harvest/api/webull.py @@ -68,8 +68,8 @@ def enter_live_trade_pin(self): return return self.api.get_trade_token(self.config["wb_trade_pin"]) - def setup(self, interval: Dict, trader=None, trader_main=None): - super().setup(interval, trader, trader_main) + def setup(self, interval: Dict, trader_main=None): + super().setup(interval, trader_main) self.watch_stock = [] self.watch_crypto = [] self.watch_crypto_fmt = [] diff --git a/harvest/api/yahoo.py b/harvest/api/yahoo.py index 3f5eb42b..30ca8af1 100644 --- a/harvest/api/yahoo.py +++ b/harvest/api/yahoo.py @@ -3,6 +3,7 @@ from typing import Any, Dict, List, Tuple # External libraries +import tzlocal import pandas as pd import yfinance as yf @@ -25,8 +26,8 @@ class YahooStreamer(API): def __init__(self, path=None): self.timestamp = now() - def setup(self, interval: Dict, trader=None, trader_main=None): - super().setup(interval, trader, trader_main) + def setup(self, interval: Dict, trader_main=None): + super().setup(interval, trader_main) self.watch_ticker = {} @@ -169,7 +170,7 @@ def fetch_chain_info(self, symbol: str): return { "id": "n/a", "exp_dates": [ - convert_input_to_datetime(s, self.trader.timezone) for s in option_list + convert_input_to_datetime(s, tzlocal.get_localzone()) for s in option_list ], "multiplier": 100, } From 3494259ae7a0d6689856625c51abc54dc31a74d2 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Wed, 10 Nov 2021 20:32:15 -0800 Subject: [PATCH 09/20] added code comments --- harvest/cli.py | 38 ++++++++++++++++++++++++++------------ harvest/trader/tester.py | 4 ++-- harvest/trader/trader.py | 4 ++-- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/harvest/cli.py b/harvest/cli.py index fa16c0d7..6fef0546 100644 --- a/harvest/cli.py +++ b/harvest/cli.py @@ -101,9 +101,8 @@ def raise_helper(): help="buys and sells assets on your behalf", choices=list(brokers.keys()), ) -# start_parser.add_argument( -# "algos", nargs="+", help="paths to algorithms you want to run" -# ) + +# Directory with algos that you want to run, default is the current working directory. start_parser.add_argument( "-d", "--directory", @@ -150,29 +149,32 @@ def start(args: argparse.Namespace, test: bool = False): debug = args.debug trader = LiveTrader(streamer=streamer, broker=broker, storage=storage, debug=debug) - # algos is a list of paths to files that have user defined algos + # Get the directories. directory = args.directory print(f"Searching directory {directory}") files = [fi for fi in listdir(directory) if isfile(join(directory, fi))] print(f"Found files {files}") + # For each file in the directory... for f in files: names = f.split(".") + # Filter out non-python files. if len(names) <= 1 or names[-1] != "py": continue name = "".join(names[:-1]) + # ...open it... with open(join(directory, f), "r") as algo_file: firstline = algo_file.readline() if firstline.find("HARVEST_SKIP") != -1: print(f"Skipping {f}") continue - # load in the entire file + # ...load in the entire file and add the algo to the trader. algo_path = os.path.realpath(join(directory, f)) spec = importlib.util.spec_from_file_location(name, algo_path) algo = importlib.util.module_from_spec(spec) spec.loader.exec_module(algo) - # iterate though the variables and if a variable is a subclass of BaseAlgo instantiate it and added to the trader + # Iterate though the variables and if a variable is a subclass of BaseAlgo instantiate it and added to the trader. for algo_cls in inspect.getmembers(algo): k, v = algo_cls[0], algo_cls[1] if inspect.isclass(v) and v != BaseAlgo and issubclass(v, BaseAlgo): @@ -184,10 +186,15 @@ def start(args: argparse.Namespace, test: bool = False): def visualize(args: argparse.Namespace): + """ + Read a csv or pickle file created by Harvest with ohlc data and graph the data. + :args: A Namespace object containing parsed user arguments. + """ import re import pandas as pd import mplfinance as mpf + # Open the file using the appropriate parser. if args.path.endswith(".csv"): df = pd.read_csv(args.path) df["timestamp"] = pd.to_datetime(df["timestamp"]) @@ -200,22 +207,29 @@ def visualize(args: argparse.Namespace): if df.empty: print(f"No data found in {args.path}.") + sys.exit(2) path = os.path.basename(args.path) + # File names are asset {ticker name}@{interval}.{file format} file_search = re.search("^(@?[\w]+)@([\w]+).(csv|pickle)$", path) symbol, interval = file_search.group(1), file_search.group(2) open_price = df.iloc[0]["open"] close_price = df.iloc[-1]["close"] high_price = df["high"].max() low_price = df["low"].min() + price_delta = close_price - open_price + price_delta_precent = 100 % (price_delta / open_price) + volume = df["volume"].sum() print(f"{symbol} at {interval}") - print("open", open_price) - print("high", high_price) - print("low", low_price) - print("close", close_price) - print("price change", close_price - open_price) - mpf.plot(df, type="candle", volume=True, show_nontrading=True) + print(f"open\t{open_price}") + print(f"high\t{high_price}") + print(f"low\t{low_price}") + print(f"close\t{close_price}") + print(f"price change\t{price_delta}") + print(f"price change percentage\t{price_delta_precent}%") + print(f"volume\t{volume}") + mpf.plot(df, type="candle", style="charles", volume=True, show_nontrading=True, title=path) def _get_storage(storage: str): diff --git a/harvest/trader/tester.py b/harvest/trader/tester.py index 4d7ec2ea..e917db8c 100644 --- a/harvest/trader/tester.py +++ b/harvest/trader/tester.py @@ -66,8 +66,8 @@ def start( a.config() self._setup(source, interval, aggregations, path, start, end, period) - self.broker.setup(self.interval, self, self.main) - self.streamer.setup(self.interval, self, self.main) + self.broker.setup(self.interval, self.main) + self.streamer.setup(self.interval, self.main) for a in self.algo: a.setup() diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index e4ed5b21..2f725a13 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -146,11 +146,11 @@ def start( self._setup_account() self.storage.init_performace_data(self.account["equity"]) - self.broker.setup(self.interval, self, self.main) + self.broker.setup(self.interval, self.main) if self.broker != self.streamer: # Only call the streamer setup if it is a different # instance than the broker otherwise some brokers can fail! - self.streamer.setup(self.interval, self, self.main) + self.streamer.setup(self.interval, self.main) # Initialize the storage self._storage_init(all_history) From 3f0ffcdcd257d27f7ed06b8c282e07c26abc93d1 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Wed, 10 Nov 2021 20:50:04 -0800 Subject: [PATCH 10/20] removed storage reliance on trader --- harvest/storage/base_storage.py | 30 ++++++++++++------------------ harvest/trader/trader.py | 5 ++--- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/harvest/storage/base_storage.py b/harvest/storage/base_storage.py index 2e632b54..9b1b24c2 100644 --- a/harvest/storage/base_storage.py +++ b/harvest/storage/base_storage.py @@ -103,12 +103,7 @@ def __init__( self.storage_performance[interval] = pd.DataFrame( columns=["equity"], index=[] ) - - def setup(self, trader): - """ - Sets up the storage - """ - self.trader = trader + def store( self, symbol: str, interval: Interval, data: pd.DataFrame, remove_duplicate=True @@ -288,13 +283,13 @@ def aggregate( ].iloc[-self.price_storage_size :] self.storage_lock.release() - def init_performace_data(self, equity: float): + def init_performace_data(self, equity: float, timestamp): for interval, days in self.performance_history_intervals: self.storage_performance[interval] = pd.DataFrame( - {"equity": [equity]}, index=[self.trader.timestamp] + {"equity": [equity]}, index=[timestamp] ) - def add_performance_data(self, equity: float): + def add_performance_data(self, equity: float, timestamp): """ Adds the performance data to the storage. @@ -304,40 +299,39 @@ def add_performance_data(self, equity: float): :param equity: Current equity of the account. """ - cur_timestamp = self.trader.timestamp # Performance history range up until '3 MONTHS' have the # same interval as the polling interval of the trader. for interval, days in self.performance_history_intervals[0:3]: df = self.storage_performance[interval] - cutoff = cur_timestamp - dt.timedelta(days=days) + cutoff = timestamp - dt.timedelta(days=days) if df.index[0] < cutoff: df = df.loc[df.index >= cutoff] - df = df.append(pd.DataFrame({"equity": [equity]}, index=[cur_timestamp])) + df = df.append(pd.DataFrame({"equity": [equity]}, index=[timestamp])) self.storage_performance[interval] = df # Performance history intervals after '3 MONTHS' are populated # only for each day. for interval, days in self.performance_history_intervals[3:5]: df = self.storage_performance[interval] - if df.index[-1].date() == cur_timestamp.date(): + if df.index[-1].date() == timestamp.date(): df = df.iloc[:-1] df = df.append( - pd.DataFrame({"equity": [equity]}, index=[cur_timestamp]) + pd.DataFrame({"equity": [equity]}, index=[timestamp]) ) else: df = df.append( - pd.DataFrame({"equity": [equity]}, index=[cur_timestamp]) + pd.DataFrame({"equity": [equity]}, index=[timestamp]) ) - cutoff = cur_timestamp - dt.timedelta(days=days) + cutoff = timestamp - dt.timedelta(days=days) if df.index[0] < cutoff: df = df.loc[df.index >= cutoff] self.storage_performance[interval] = df df = self.storage_performance["ALL"] - if df.index[-1].date() == cur_timestamp.date(): + if df.index[-1].date() == timestamp.date(): df = df.iloc[:-1] - df = df.append(pd.DataFrame({"equity": [equity]}, index=[cur_timestamp])) + df = df.append(pd.DataFrame({"equity": [equity]}, index=[timestamp])) self.storage_performance["ALL"] = df debugger.debug("Performance data added") diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index 2f725a13..4a37b19f 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -47,7 +47,6 @@ def __init__(self, streamer=None, broker=None, storage=None, debug=False): self._set_streamer_broker(streamer, broker) # Initialize the storage self.storage = BaseStorage() if storage is None else storage - self.storage.setup(self) self._init_attributes() self._setup_debugger(debug) @@ -144,7 +143,7 @@ def start( # Initialize the account self._setup_account() - self.storage.init_performace_data(self.account["equity"]) + self.storage.init_performace_data(self.account["equity"], self.timestamp) self.broker.setup(self.interval, self.main) if self.broker != self.streamer: @@ -282,7 +281,7 @@ def main(self, df_dict): if self.timestamp.hour % 12 == 0 and self.timestamp.minute == 0: self.streamer.refresh_cred() - self.storage.add_performance_data(self.account["equity"]) + self.storage.add_performance_data(self.account["equity"], self.timestamp) # Save the data locally for sym in df_dict: From 02c13410dc167b69eb25449065dfd0e9858699f6 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Wed, 10 Nov 2021 22:26:15 -0800 Subject: [PATCH 11/20] updated harvest workflows --- docs/dev.md | 25 ++++++++++++++++++++----- docs/fetch-data.png | Bin 0 -> 65455 bytes docs/run-algo.png | Bin 0 -> 67378 bytes 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 docs/fetch-data.png create mode 100644 docs/run-algo.png diff --git a/docs/dev.md b/docs/dev.md index 3207ae8d..e92d77d3 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -1,7 +1,22 @@ -# Overview +## The Harvest Workflow -### Harvest architecture -![Harvest architecture](harvest_architecture.png) +Because Harvest is an extensive framework it can be hard to understand how the system works at times. This document server to provide a high-level overview of just how Harvests works after a user starts the trader. -### Harvest Flow on Trader `start()` -![Harvest start flow](harvest_start_flow.png) \ No newline at end of file +## Fetching Data + +After the user starts the trader Harvest will fetch data from the streamer and update its storage on interval. + +![Fetching Data Workflow](fetch-data.png) + +1. First Harvest will run the streamer on the specified interval. Once the data has been collected, the streamer will call a callback or hook function that will pass operation back to the trader. In this callback function the streamer will return the latest OHLC data for the assets specified by the trader. +2. In this callback, the trader will update the storage with the latest data and the will run each algorithm. + +## Running Algorithms + +After data is fetched, the algorithms are run linearly. + +![Running Algorithm Workflow](run-algo.png) + +1. The algorithm the user created will user functions provided in the `BaseAlgo` class which communicate with the Trader. +2. Typically the user's algorithms will first ask for data on the assets they specified which will be stored in the Storage. +3. After that the user's algoirthms will decided when to buy or sell assets based on the data they got from the Storage. This will leverage the Broker. \ No newline at end of file diff --git a/docs/fetch-data.png b/docs/fetch-data.png new file mode 100644 index 0000000000000000000000000000000000000000..30a4eb65c19161dbda753afb2a6419d62c08190f GIT binary patch literal 65455 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 literal 0 HcmV?d00001 diff --git a/docs/run-algo.png b/docs/run-algo.png new file mode 100644 index 0000000000000000000000000000000000000000..c01f09f73b732be516d13a197719f753e8dd4396 GIT binary patch literal 67378 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

6Jy!n8hXHOmWzp$Az^GW@?+d3m3IsJ;w?${4`Q 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 Yt$7}e-^K5Imeb@WMwW(Um)suy2T|_VGynhq literal 0 HcmV?d00001 From 626a490ab2e4dcaa6b2ba2836702ef5b83cb0b8b Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Thu, 11 Nov 2021 20:38:38 -0800 Subject: [PATCH 12/20] fixed many tests --- harvest/api/_base.py | 10 +++++----- harvest/api/paper.py | 36 +++++++++++++++--------------------- harvest/api/robinhood.py | 2 +- harvest/trader/tester.py | 12 ++++++------ tests/test_api.py | 34 ++++++++++++++++++++++++++-------- tests/test_api_paper.py | 9 +-------- tests/test_api_webull.py | 4 ++-- tests/test_api_yahoo.py | 8 ++++---- tests/test_storage_csv.py | 6 +++--- tests/test_storage_pickle.py | 6 +++--- tests/test_tester.py | 2 +- 11 files changed, 67 insertions(+), 62 deletions(-) diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 4e27585d..0d0c5705 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -233,6 +233,7 @@ def _run_once(func): ran = False def wrapper(*args, **kwargs): + nonlocal ran if not ran: ran = True return func(*args, **kwargs) @@ -529,7 +530,7 @@ def order_stock_limit( Raises an exception if order fails. """ raise NotImplementedError( - f"{type(self).__name__} does not support this broker method: `order_limit`." + f"{type(self).__name__} does not support this broker method: `order_stock_limit`." ) def order_crypto_limit( @@ -557,7 +558,7 @@ def order_crypto_limit( Raises an exception if order fails. """ raise NotImplementedError( - f"{type(self).__name__} does not support this broker method: `order_limit`." + f"{type(self).__name__} does not support this broker method: `order_crypto_limit`." ) def order_option_limit( @@ -867,7 +868,7 @@ def main(self, df_dict): # If there are data that has not been received, start a timer if self.first: - timer = threading.Thread(self.timeout, daemon=True) + timer = threading.Thread(target=self.timeout, daemon=True) timer.start() self.all_recv = False self.first = False @@ -893,9 +894,8 @@ def flush(self): 'low': 0, 'close': 0, 'volume': 0 - }) + }, index=[self.timestamp]) - data.index = [self.timestamp] self.block_queue[n] = data self.block_lock.release() self.trader_main(self.block_queue) diff --git a/harvest/api/paper.py b/harvest/api/paper.py index c68e1d19..ada85628 100644 --- a/harvest/api/paper.py +++ b/harvest/api/paper.py @@ -9,6 +9,7 @@ # Submodule imports from harvest.api._base import API +from harvest.api.dummy import DummyStreamer from harvest.utils import * @@ -27,7 +28,7 @@ class PaperBroker(API): Interval.DAY_1, ] - def __init__(self, account_path: str = None, commission_fee=0): + def __init__(self, account_path: str = None, commission_fee=0, streamer=None): """ :commission_fee: When this is a number it is assumed to be a flat price on all buys and sells of assets. When this is a string formatted as @@ -50,6 +51,11 @@ def __init__(self, account_path: str = None, commission_fee=0): self.commission_fee = commission_fee self.id = 0 + if streamer is None: + self.streamer = DummyStreamer() + else: + self.streamer = streamer + if account_path: with open(account_path, "r") as f: account = yaml.safe_load(f) @@ -89,11 +95,7 @@ def fetch_crypto_positions(self) -> List[Dict[str, Any]]: def update_option_positions(self, positions) -> List[Dict[str, Any]]: for r in self.options: occ_sym = r["symbol"] - - if self.trader is None: - price = self.fetch_option_market_data(occ_sym)["price"] - else: - price = self.trader.streamer.fetch_option_market_data(occ_sym)["price"] + price = self.fetch_option_market_data(occ_sym)["price"] r["current_price"] = price r["market_value"] = price * r["quantity"] * 100 @@ -112,17 +114,12 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: ret = next(r for r in self.orders if r["id"] == id) sym = ret["symbol"] - if self.trader is None: - price = self.streamer.fetch_price_history( - sym, - self.interval[sym]["interval"], - dt.datetime.now() - dt.timedelta(days=7), - dt.datetime.now(), - )[sym]["close"][-1] - else: - price = self.trader.storage.load(sym, self.interval[sym]["interval"])[sym][ - "close" - ][-1] + price = self.streamer.fetch_price_history( + sym, + self.interval[sym]["interval"], + dt.datetime.now() - dt.timedelta(days=7), + dt.datetime.now(), + )[sym]["close"][-1] qty = ret["quantity"] original_price = price * qty @@ -194,10 +191,7 @@ def fetch_option_order_status(self, id: int) -> Dict[str, Any]: sym = ret["base_symbol"] occ_sym = ret["symbol"] - if self.trader is None: - price = self.streamer.fetch_option_market_data(occ_sym)["price"] - else: - price = self.trader.streamer.fetch_option_market_data(occ_sym)["price"] + price = self.streamer.fetch_option_market_data(occ_sym)["price"] qty = ret["quantity"] original_price = price * qty diff --git a/harvest/api/robinhood.py b/harvest/api/robinhood.py index 6cd63011..f67c755d 100644 --- a/harvest/api/robinhood.py +++ b/harvest/api/robinhood.py @@ -42,7 +42,7 @@ def refresh_cred(self): debugger.debug("Logged into Robinhood...") # @API._run_once - def setup(self, interval trader_main=None): + def setup(self, interval, trader_main=None): super().setup(interval, trader_main) diff --git a/harvest/trader/tester.py b/harvest/trader/tester.py index e917db8c..a9513914 100644 --- a/harvest/trader/tester.py +++ b/harvest/trader/tester.py @@ -118,7 +118,7 @@ def _setup( common_end = None for s in self.interval: for i in [self.interval[s]["interval"]] + self.interval[s]["aggregations"]: - df = self.storage.load(s, i, no_slice=True) + df = self.storage.load(s, i) df = pandas_datetime_to_utc(df, self.timezone) if common_start is None or df.index[0] > common_start: common_start = df.index[0] @@ -146,7 +146,7 @@ def _setup( for s in self.interval: for i in [self.interval[s]["interval"]] + self.interval[s]["aggregations"]: - df = self.storage.load(s, i, no_slice=True).copy() + df = self.storage.load(s, i).copy() df = df.loc[start:end] self.storage.reset(s, i) self.storage.store(s, i, df) @@ -198,7 +198,7 @@ def _setup( debugger.debug("Formatting complete") for sym in self.interval: for agg in self.interval[sym]["aggregations"]: - data = self.storage.load(sym, int(agg) - 16, no_slice=True) + data = self.storage.load(sym, int(agg) - 16) data = pandas_datetime_to_utc(data, self.timezone) self.storage.store( sym, @@ -219,13 +219,13 @@ def _setup( self.df[sym] = {} inter = self.interval[sym]["interval"] interval_txt = interval_enum_to_string(inter) - df = self.storage.load(sym, inter, no_slice=True) + df = self.storage.load(sym, inter) self.df[sym][inter] = df.copy() for agg in self.interval[sym]["aggregations"]: # agg_txt = interval_enum_to_string(agg) # agg_txt = f"{interval_txt}+{agg_txt}" - df = self.storage.load(sym, int(agg) - 16, no_slice=True) + df = self.storage.load(sym, int(agg) - 16) self.df[sym][int(agg) - 16] = df.copy() # Trim data so start and end dates match between assets and intervals @@ -328,7 +328,7 @@ def run_backtest(self): df_dict[sym] = self.df[sym][inter].loc[self.timestamp] update = self._update_order_queue() - self._update_stats(df_dict, new=update, option_update=True) + self._update_position_cache(df_dict, new=update, option_update=True) for sym in self.interval: inter = self.interval[sym]["interval"] if is_freq(self.timestamp, inter): diff --git a/tests/test_api.py b/tests/test_api.py index f109596a..b4e16232 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -25,7 +25,7 @@ def setUpClass(self): def test_timeout(self): stream = StreamAPI() stream.fetch_account = lambda: None - stream.fetch_price_history = lambda x, y: pd.DataFrame() + stream.fetch_price_history = lambda x, y, z: pd.DataFrame() stream.fetch_account = lambda: {"cash": 100, "equity": 100} t = PaperTrader(stream) stream.trader = t @@ -75,7 +75,7 @@ def test_timeout(self): def test_timeout_cancel(self): stream = StreamAPI() stream.fetch_account = lambda: None - stream.fetch_price_history = lambda x, y: pd.DataFrame() + stream.fetch_price_history = lambda x, y, z: pd.DataFrame() stream.fetch_account = lambda: {"cash": 100, "equity": 100} t = PaperTrader(stream) t.set_algo(BaseAlgo()) @@ -185,10 +185,16 @@ def test_exceptions(self): self.assertEqual(str(e), "API does not support this broker method: `fetch_crypto_order_status`.") try: - api.order_limit("buy", "A", 5, 7) + api.order_stock_limit("buy", "A", 5, 7) self.assertTrue(False) except NotImplementedError as e: - self.assertEqual(str(e), "API does not support this broker method: `order_limit`.") + self.assertEqual(str(e), "API does not support this broker method: `order_stock_limit`.") + + try: + api.order_crypto_limit("buy", "@A", 5, 7) + self.assertTrue(False) + except NotImplementedError as e: + self.assertEqual(str(e), "API does not support this broker method: `order_crypto_limit`.") try: api.order_option_limit("buy", "A", 5, 7, "call", now(), 8) @@ -196,6 +202,20 @@ def test_exceptions(self): except NotImplementedError as e: self.assertEqual(str(e), "API does not support this broker method: `order_option_limit`.") + try: + api.buy('A', -1, 0) + self.assertTrue(False) + except NotImplementedError as e: + self.assertEqual(str(e), "API does not support this broker method: `order_stock_limit`.") + + try: + api.sell('A', -1, 0) + self.assertTrue(False) + except NotImplementedError as e: + self.assertEqual(str(e), "API does not support this broker method: `order_stock_limit`.") + + + def test_base_cases(self): api = API() @@ -206,15 +226,13 @@ def test_base_cases(self): self.assertEqual(api.fetch_crypto_positions(), []) api.update_option_positions([]) self.assertEqual(api.fetch_order_queue(), []) - self.assertTrue(api.buy('A', -1) is None) - self.assertTrue(api.buy_option("A", -1) is None) def test_run_once(self): api = API() fn = lambda x: x + 1 wrapper = API._run_once(fn) - self.assertEqual(wrapper(api)(5), 6) - self.assertTrue(wrapper(api) is None) + self.assertEqual(wrapper(5), 6) + self.assertTrue(wrapper(5) is None) def test_timestamp(self): api = API() diff --git a/tests/test_api_paper.py b/tests/test_api_paper.py index ec640eba..ab719081 100644 --- a/tests/test_api_paper.py +++ b/tests/test_api_paper.py @@ -12,7 +12,6 @@ class TestPaperBroker(unittest.TestCase): def test_account(self): dummy = PaperBroker() - dummy.streamer = DummyStreamer() d = dummy.fetch_account() self.assertEqual(d["equity"], 1000000.0) self.assertEqual(d["cash"], 1000000.0) @@ -22,7 +21,6 @@ def test_account(self): def test_dummy_account(self): directory = pathlib.Path(__file__).parent.resolve() dummy = PaperBroker(str(directory) + "/../dummy_account.yaml") - dummy.streamer = DummyStreamer() stocks = dummy.fetch_stock_positions() self.assertEqual(len(stocks), 2) self.assertEqual(stocks[0]["symbol"], "A") @@ -37,7 +35,6 @@ def test_dummy_account(self): def test_buy_order_limit(self): dummy = PaperBroker() - dummy.streamer = DummyStreamer() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) order = dummy.order_stock_limit("buy", "A", 5, 50000) @@ -56,10 +53,9 @@ def test_buy_order_limit(self): def test_buy(self): dummy = PaperBroker() - dummy.streamer = DummyStreamer() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) - order = dummy.buy("A", 5) + order = dummy.buy("A", 5, 7) self.assertEqual(order["type"], "STOCK") self.assertEqual(order["id"], 0) self.assertEqual(order["symbol"], "A") @@ -76,7 +72,6 @@ def test_buy(self): def test_sell_order_limit(self): directory = pathlib.Path(__file__).parent.resolve() dummy = PaperBroker(str(directory) + "/../dummy_account.yaml") - dummy.streamer = DummyStreamer() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) order = dummy.order_stock_limit("sell", "A", 2, 50000) @@ -96,7 +91,6 @@ def test_sell_order_limit(self): def test_sell(self): directory = pathlib.Path(__file__).parent.resolve() dummy = PaperBroker(str(directory) + "/../dummy_account.yaml") - dummy.streamer = DummyStreamer() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) order = dummy.sell("A", 2) @@ -115,7 +109,6 @@ def test_sell(self): def test_order_option_limit(self): dummy = PaperBroker() - dummy.streamer = DummyStreamer() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) exp_date = dt.datetime.now() + dt.timedelta(hours=5) diff --git a/tests/test_api_webull.py b/tests/test_api_webull.py index 3656cebd..2fe0220d 100644 --- a/tests/test_api_webull.py +++ b/tests/test_api_webull.py @@ -58,7 +58,7 @@ def test_main(df): "@BTC": {"interval": Interval.MIN_1, "aggregations": []}, "SPY": {"interval": Interval.MIN_1, "aggregations": []}, } - wb.setup(interval, None, test_main) + wb.setup(interval, test_main) wb.main() @not_gh_action @@ -72,7 +72,7 @@ def test_main(df): wb = Webull() watch = ["SPY"] interval = {"SPY": {"interval": Interval.MIN_1, "aggregations": []}} - wb.setup(interval, None, test_main) + wb.setup(interval, test_main) wb.main() @not_gh_action diff --git a/tests/test_api_yahoo.py b/tests/test_api_yahoo.py index f9734e67..46994d1a 100644 --- a/tests/test_api_yahoo.py +++ b/tests/test_api_yahoo.py @@ -43,7 +43,7 @@ def test_main(df): yh = YahooStreamer() watch = ["SPY", "AAPL", "@BTC"] - yh.setup(interval, None, test_main) + yh.setup(interval, test_main) yh.main() def test_main_single(self): @@ -54,14 +54,14 @@ def test_main(df): self.assertEqual(df["SPY"].columns[0][0], "SPY") yh = YahooStreamer() - yh.setup(interval, None, test_main) + yh.setup(interval, test_main) yh.main() def test_chain_info(self): t = PaperTrader() yh = YahooStreamer() interval = {"LMND": {"interval": Interval.MIN_1, "aggregations": []}} - yh.setup(interval, t, None) + yh.setup(interval) info = yh.fetch_chain_info("LMND") self.assertGreater(len(info["exp_dates"]), 0) @@ -69,7 +69,7 @@ def test_chain_data(self): t = PaperTrader() yh = YahooStreamer() interval = {"LMND": {"interval": Interval.MIN_1, "aggregations": []}} - yh.setup(interval, t, None) + yh.setup(interval) dates = yh.fetch_chain_info("LMND")["exp_dates"] data = yh.fetch_chain_data("LMND", dates[0]) self.assertGreater(len(data), 0) diff --git a/tests/test_storage_csv.py b/tests/test_storage_csv.py index 319901f5..156b193f 100644 --- a/tests/test_storage_csv.py +++ b/tests/test_storage_csv.py @@ -18,7 +18,7 @@ def setUpClass(self): def test_create_storage(self): storage = CSVStorage(self.storage_dir) - self.assertEqual(storage.storage, {}) + self.assertEqual(storage.storage_price, {}) def test_simple_store(self): storage = CSVStorage(self.storage_dir) @@ -26,8 +26,8 @@ def test_simple_store(self): storage.store("A", Interval.MIN_1, data.copy(True)) self.assertTrue(not pd.isna(data.iloc[0]["A"]["low"])) - self.assertTrue("A" in list(storage.storage.keys())) - self.assertEqual(list(storage.storage["A"].keys()), [Interval.MIN_1]) + self.assertTrue("A" in list(storage.storage_price.keys())) + self.assertEqual(list(storage.storage_price["A"].keys()), [Interval.MIN_1]) def test_saved_load(self): storage1 = CSVStorage(self.storage_dir) diff --git a/tests/test_storage_pickle.py b/tests/test_storage_pickle.py index 808724ef..59684af6 100644 --- a/tests/test_storage_pickle.py +++ b/tests/test_storage_pickle.py @@ -18,7 +18,7 @@ def setUpClass(self): def test_create_storage(self): storage = PickleStorage(self.storage_dir) - self.assertEqual(storage.storage, {}) + self.assertEqual(storage.storage_price, {}) def test_simple_store(self): storage = PickleStorage(self.storage_dir) @@ -26,8 +26,8 @@ def test_simple_store(self): storage.store("A", Interval.MIN_1, data.copy(True)) self.assertTrue(not pd.isna(data.iloc[0]["A"]["low"])) - self.assertTrue("A" in list(storage.storage.keys())) - self.assertEqual(list(storage.storage["A"].keys()), [Interval.MIN_1]) + self.assertTrue("A" in list(storage.storage_price.keys())) + self.assertEqual(list(storage.storage_price["A"].keys()), [Interval.MIN_1]) def test_saved_load(self): storage1 = PickleStorage(self.storage_dir) diff --git a/tests/test_tester.py b/tests/test_tester.py index 805f64f2..b0bcc67a 100644 --- a/tests/test_tester.py +++ b/tests/test_tester.py @@ -43,7 +43,7 @@ def test_check_aggregation(self): minutes = list(t.storage.load("A", Interval.MIN_1)["A"]["close"])[-200:] days_agg = list( - t.storage.load("A", int(Interval.DAY_1) - 16, no_slice=True)["A"]["close"] + t.storage.load("A", int(Interval.DAY_1) - 16)["A"]["close"] )[-200:] self.assertListEqual(minutes, days_agg) From 793ab596278d39f98a7e891ee9b80016c5ea80db Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Thu, 11 Nov 2021 21:40:59 -0800 Subject: [PATCH 13/20] linted --- harvest/algo.py | 4 +++- harvest/api/_base.py | 22 ++++++++++------------ harvest/api/paper.py | 10 +++++----- harvest/api/yahoo.py | 3 ++- harvest/cli.py | 11 +++++++++-- harvest/storage/base_storage.py | 9 ++------- harvest/trader/trader.py | 31 +++++++++++++++++-------------- harvest/utils.py | 1 + tests/test_algo.py | 2 +- 9 files changed, 50 insertions(+), 43 deletions(-) diff --git a/harvest/algo.py b/harvest/algo.py index 719fcc73..f55a6b40 100644 --- a/harvest/algo.py +++ b/harvest/algo.py @@ -770,7 +770,9 @@ def get_datetime(self): :returns: The current date and time as a datetime object """ - return datetime_utc_to_local(self.trader.timestamp, self.trader.timezone) + return datetime_utc_to_local( + self.trader.streamer.timestamp, self.trader.timezone + ) def get_option_position_quantity(self, symbol: str = None) -> bool: """Returns the number of types of options held for a stock. diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 0d0c5705..8c398f7f 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -177,8 +177,8 @@ def main(self): df_dict = {} for sym in self.interval: inter = self.interval[sym]["interval"] - if is_freq(self.timestamp, inter): - n = self.timestamp + if is_freq(harvest_timestamp, inter): + n = harvest_timestamp latest = self.fetch_price_history( sym, inter, n - interval_to_timedelta(inter) * 2, n ) @@ -224,14 +224,15 @@ def wrapper(*args, **kwargs): return wrapper def _run_once(func): - """ + """ Wrapper to only allows wrapped functions to be run once. :func: Function to wrap. - :returns: The return of the inputted function if it has not been run before and None otherwise. + :returns: The return of the inputted function if it has not been run before and None otherwise. """ ran = False + def wrapper(*args, **kwargs): nonlocal ran if not ran: @@ -252,7 +253,7 @@ def fetch_price_history( ) -> pd.DataFrame: """ Fetches historical price data for the specified asset and period - using the API. The first row is the earliest entry and the last + using the API. The first row is the earliest entry and the last row is the latest entry. :param symbol: The stock/crypto to get data for. @@ -888,13 +889,10 @@ def flush(self): # For missing data, return a OHLC with all zeroes. self.block_lock.acquire() for n in self.needed: - data = pd.DataFrame({ - 'open': 0, - 'high': 0, - 'low': 0, - 'close': 0, - 'volume': 0 - }, index=[self.timestamp]) + data = pd.DataFrame( + {"open": 0, "high": 0, "low": 0, "close": 0, "volume": 0}, + index=[self.timestamp], + ) self.block_queue[n] = data self.block_lock.release() diff --git a/harvest/api/paper.py b/harvest/api/paper.py index ada85628..613943c6 100644 --- a/harvest/api/paper.py +++ b/harvest/api/paper.py @@ -95,7 +95,7 @@ def fetch_crypto_positions(self) -> List[Dict[str, Any]]: def update_option_positions(self, positions) -> List[Dict[str, Any]]: for r in self.options: occ_sym = r["symbol"] - price = self.fetch_option_market_data(occ_sym)["price"] + price = self.streamer.fetch_option_market_data(occ_sym)["price"] r["current_price"] = price r["market_value"] = price * r["quantity"] * 100 @@ -157,7 +157,7 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: self.orders.remove(ret) ret = ret_1 ret["status"] = "filled" - ret["filled_time"] = self.trader.timestamp + ret["filled_time"] = self.streamer.timestamp ret["filled_price"] = price else: if pos is None: @@ -175,7 +175,7 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: self.orders.remove(ret) ret = ret_1 ret["status"] = "filled" - ret["filled_time"] = self.trader.timestamp + ret["filled_time"] = self.streamer.timestamp ret["filled_price"] = price self.equity = self._calc_equity() @@ -237,7 +237,7 @@ def fetch_option_order_status(self, id: int) -> Dict[str, Any]: self.cash -= actual_price self.buying_power -= actual_price ret["status"] = "filled" - ret["filled_time"] = self.trader.timestamp + ret["filled_time"] = self.streamer.timestamp ret["filled_price"] = price debugger.debug(f"After BUY: {self.buying_power}") ret_1 = ret.copy() @@ -259,7 +259,7 @@ def fetch_option_order_status(self, id: int) -> Dict[str, Any]: if pos["quantity"] < 1e-8: self.options.remove(pos) ret["status"] = "filled" - ret["filled_time"] = self.trader.timestamp + ret["filled_time"] = self.streamer.timestamp ret["filled_price"] = price ret_1 = ret.copy() self.orders.remove(ret) diff --git a/harvest/api/yahoo.py b/harvest/api/yahoo.py index 30ca8af1..0d974902 100644 --- a/harvest/api/yahoo.py +++ b/harvest/api/yahoo.py @@ -170,7 +170,8 @@ def fetch_chain_info(self, symbol: str): return { "id": "n/a", "exp_dates": [ - convert_input_to_datetime(s, tzlocal.get_localzone()) for s in option_list + convert_input_to_datetime(s, tzlocal.get_localzone()) + for s in option_list ], "multiplier": 100, } diff --git a/harvest/cli.py b/harvest/cli.py index 6fef0546..bbe4b9d6 100644 --- a/harvest/cli.py +++ b/harvest/cli.py @@ -210,7 +210,7 @@ def visualize(args: argparse.Namespace): sys.exit(2) path = os.path.basename(args.path) - # File names are asset {ticker name}@{interval}.{file format} + # File names are asset {ticker name}@{interval}.{file format} file_search = re.search("^(@?[\w]+)@([\w]+).(csv|pickle)$", path) symbol, interval = file_search.group(1), file_search.group(2) open_price = df.iloc[0]["open"] @@ -229,7 +229,14 @@ def visualize(args: argparse.Namespace): print(f"price change\t{price_delta}") print(f"price change percentage\t{price_delta_precent}%") print(f"volume\t{volume}") - mpf.plot(df, type="candle", style="charles", volume=True, show_nontrading=True, title=path) + mpf.plot( + df, + type="candle", + style="charles", + volume=True, + show_nontrading=True, + title=path, + ) def _get_storage(storage: str): diff --git a/harvest/storage/base_storage.py b/harvest/storage/base_storage.py index 9b1b24c2..c234f320 100644 --- a/harvest/storage/base_storage.py +++ b/harvest/storage/base_storage.py @@ -103,7 +103,6 @@ def __init__( self.storage_performance[interval] = pd.DataFrame( columns=["equity"], index=[] ) - def store( self, symbol: str, interval: Interval, data: pd.DataFrame, remove_duplicate=True @@ -316,13 +315,9 @@ def add_performance_data(self, equity: float, timestamp): df = self.storage_performance[interval] if df.index[-1].date() == timestamp.date(): df = df.iloc[:-1] - df = df.append( - pd.DataFrame({"equity": [equity]}, index=[timestamp]) - ) + df = df.append(pd.DataFrame({"equity": [equity]}, index=[timestamp])) else: - df = df.append( - pd.DataFrame({"equity": [equity]}, index=[timestamp]) - ) + df = df.append(pd.DataFrame({"equity": [equity]}, index=[timestamp])) cutoff = timestamp - dt.timedelta(days=days) if df.index[0] < cutoff: df = df.loc[df.index >= cutoff] diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index 4a37b19f..c54ba341 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -74,9 +74,6 @@ def _init_attributes(self): signal(SIGINT, self.exit) - # Initialize timestamp - self.timestamp = self.streamer.timestamp - self.watchlist_global = [] # List of securities specified in this class self.algo = [] # List of algorithms to run. self.account = {} # Local cache of account data. @@ -143,7 +140,9 @@ def start( # Initialize the account self._setup_account() - self.storage.init_performace_data(self.account["equity"], self.timestamp) + self.storage.init_performace_data( + self.account["equity"], self.streamer.timestamp + ) self.broker.setup(self.interval, self.main) if self.broker != self.streamer: @@ -276,12 +275,16 @@ def main(self, df_dict): """ Main loop of the Trader. """ - self.timestamp = self.streamer.timestamp # Periodically refresh access tokens - if self.timestamp.hour % 12 == 0 and self.timestamp.minute == 0: + if ( + self.streamer.timestamp.hour % 12 == 0 + and self.streamer.timestamp.minute == 0 + ): self.streamer.refresh_cred() - self.storage.add_performance_data(self.account["equity"], self.timestamp) + self.storage.add_performance_data( + self.account["equity"], self.streamer.timestamp + ) # Save the data locally for sym in df_dict: @@ -301,7 +304,7 @@ def main(self, df_dict): new_algo = [] for a in self.algo: - if not is_freq(self.timestamp, a.interval): + if not is_freq(self.streamer.timestamp, a.interval): new_algo.append(a) continue try: @@ -454,7 +457,7 @@ def buy(self, symbol: str, quantity: int, in_force: str, extended: bool): debugger.debug("BUY failed") return None self.order_queue.append(ret) - debugger.debug(f"BUY: {self.timestamp}, {symbol}, {quantity}") + debugger.debug(f"BUY: {self.streamer.timestamp}, {symbol}, {quantity}") return ret @@ -481,7 +484,7 @@ def sell(self, symbol: str, quantity: int, in_force: str, extended: bool): debugger.debug("SELL failed") return None self.order_queue.append(ret) - debugger.debug(f"SELL: {self.timestamp}, {symbol}, {quantity}") + debugger.debug(f"SELL: {self.streamer.timestamp}, {symbol}, {quantity}") return ret # ================ Helper Functions ====================== @@ -531,9 +534,9 @@ def get_asset_quantity( # if ret is None: # raise Exception("BUY failed") # self.order_queue.append(ret) - # debugger.debug(f"BUY: {self.timestamp}, {symbol}, {quantity}") + # debugger.debug(f"BUY: {self.streamer.timestamp}, {symbol}, {quantity}") # debugger.debug(f"BUY order queue: {self.order_queue}") - # self.logger.add_transaction(self.timestamp, "buy", "option", symbol, quantity) + # self.logger.add_transaction(self.streamer.timestamp, "buy", "option", symbol, quantity) # return ret # def sell_option(self, symbol: str, quantity: int, in_force: str): @@ -553,9 +556,9 @@ def get_asset_quantity( # if ret is None: # raise Exception("SELL failed") # self.order_queue.append(ret) - # debugger.debug(f"SELL: {self.timestamp}, {symbol}, {quantity}") + # debugger.debug(f"SELL: {self.streamer.timestamp}, {symbol}, {quantity}") # debugger.debug(f"SELL order queue: {self.order_queue}") - # self.logger.add_transaction(self.timestamp, "sell", "option", symbol, quantity) + # self.logger.add_transaction(self.streamer.timestamp, "sell", "option", symbol, quantity) # return ret def set_algo(self, algo): diff --git a/harvest/utils.py b/harvest/utils.py index 43cdc546..78677b74 100644 --- a/harvest/utils.py +++ b/harvest/utils.py @@ -12,6 +12,7 @@ # External Imports import pandas as pd +# Configure a logger used by all of Harvest. logging.basicConfig( level=logging.INFO, format="%(asctime)s : %(name)s : %(levelname)s : %(message)s", diff --git a/tests/test_algo.py b/tests/test_algo.py index c657f4a0..913acab2 100644 --- a/tests/test_algo.py +++ b/tests/test_algo.py @@ -254,7 +254,7 @@ def test_buy_sell_option_auto(self, mock_mark_up): p = t.option_positions[0] self.assertEqual(p["symbol"], "X 110101C01000000") - t.algo[0].sell_option() + t.algo[0].sell_all_options() streamer.tick() # p = t.stock_positions[0] From dccea6e69ac0c0e1e7ffeee950c70a8567d887b8 Mon Sep 17 00:00:00 2001 From: tfukaza <40327230+tfukaza@users.noreply.github.com> Date: Fri, 12 Nov 2021 23:43:34 -0800 Subject: [PATCH 14/20] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 967de5bd..bcf9911d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![Header](docs/banner.png)
-Harvest is a Python framework providing a **simple** and **flexible** framework for algorithmic trading. Visit Harvest's [**website**](https://tfukaza.github.io/harvest-website/) for details, tutorials, and documentation. +Harvest is a simple yet flexible Python framework for algorithmic trading. Paper trade and live trade stocks, cryptos, and options![^1][^2] Visit Harvest's [**website**](https://tfukaza.github.io/harvest-website/) for details, tutorials, and documentation.
@@ -77,3 +77,6 @@ Currently looking for... - Many of the brokers were also not designed to be used for algo-trading. Excessive access to their API can result in your account getting locked. - Tutorials and documentation solely exist to provide technical references of the code. They are not recommendations of any specific securities or strategies. - Use Harvest at your own responsibility. Developers of Harvest take no responsibility for any financial losses you incur by using Harvest. By using Harvest, you certify you understand that Harvest is a software in early development and may contain bugs and unexpected behaviors. + +[^1]: What assets you can trade depends on the broker you are using. +[^2]: Backtesting is also available, but it is not supported for options. From 694defa7bd803236aa7025bcd451759ff0cec973 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sat, 13 Nov 2021 15:57:35 -0800 Subject: [PATCH 15/20] fixed tests --- harvest/algo.py | 2 +- harvest/api/_base.py | 10 ++++++++-- harvest/api/dummy.py | 41 +++++++++++++++++++++------------------- harvest/api/paper.py | 18 +++++++----------- harvest/trader/trader.py | 9 ++++++--- tests/test_api.py | 10 +++------- tests/test_api_paper.py | 6 +++--- 7 files changed, 50 insertions(+), 46 deletions(-) diff --git a/harvest/algo.py b/harvest/algo.py index f55a6b40..18610722 100644 --- a/harvest/algo.py +++ b/harvest/algo.py @@ -163,7 +163,7 @@ def sell_all_options(self, symbol: str = None, in_force: str = "gtc"): for s in symbols: debugger.debug(f"Algo SELL OPTION: {s}") quantity = self.get_asset_quantity(s) - ret.append(self.trader.sell_option(s, quantity, in_force)) + ret.append(self.trader.sell(s, quantity, in_force, True)) return ret diff --git a/harvest/api/_base.py b/harvest/api/_base.py index 8c398f7f..e63e7952 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -70,7 +70,9 @@ def create_secret(self, path: str): """ This method is called when the yaml file with credentials is not found.""" - raise Exception(f"{path} was not found.") + # raise Exception(f"{path} was not found.") + debugger.warning(f"Assuming API does not need account information.") + return False def refresh_cred(self): """ @@ -244,6 +246,9 @@ def wrapper(*args, **kwargs): # -------------- Streamer methods -------------- # + def get_current_time(self): + return now() + def fetch_price_history( self, symbol: str, @@ -894,7 +899,8 @@ def flush(self): index=[self.timestamp], ) + data.columns = pd.MultiIndex.from_product([[n], data.columns]) self.block_queue[n] = data self.block_lock.release() self.trader_main(self.block_queue) - self.block_queue = {} + self.block_queue = {} \ No newline at end of file diff --git a/harvest/api/dummy.py b/harvest/api/dummy.py index 4f0fc8dc..7aa078ef 100644 --- a/harvest/api/dummy.py +++ b/harvest/api/dummy.py @@ -27,21 +27,22 @@ class DummyStreamer(API): Interval.HR_1, Interval.DAY_1, ] - default_now = dt.datetime(year=2000, month=1, day=1, hour=0, minute=0) + + default_timestamp = dt.datetime(year=2000, month=1, day=1, hour=0, minute=0) def __init__( self, - path: str = None, - now: dt.datetime = default_now, + timestamp: dt.datetime = default_timestamp, realistic_times: bool = False, ): + super().__init__(None) + self.trader_main = None self.realistic_times = realistic_times # Set the current time - self._set_now(now) - self.timestamp = self.now + self._set_timestamp(timestamp) # Used so `fetch_price_history` can work without running `setup` self.interval = self.interval_list[0] # Store random values and generates for each asset tot make `fetch_price_history` fixed @@ -65,7 +66,7 @@ def fetch_latest_stock_price(self) -> Dict[str, pd.DataFrame]: """ results = {} - today = self.now + today = self.timestamp last = today - dt.timedelta(days=3) for symbol in self.interval: @@ -83,7 +84,7 @@ def fetch_latest_crypto_price(self) -> Dict[str, pd.DataFrame]: """ results = {} - today = self.now + today = self.timestamp last = today - dt.timedelta(days=3) for symbol in self.interval: if is_crypto(symbol): @@ -94,6 +95,9 @@ def fetch_latest_crypto_price(self) -> Dict[str, pd.DataFrame]: # -------------- Streamer methods -------------- # + def get_current_time(self): + return self.timestamp + def fetch_price_history( self, symbol: str, @@ -109,14 +113,14 @@ def fetch_price_history( Interval.MIN_15, Interval.MIN_30, ]: - start = self.now - dt.timedelta(days=2) + start = self.timestamp - dt.timedelta(days=2) elif interval == Interval.HR_1: - start = self.now - dt.timedelta(days=14) + start = self.timestamp - dt.timedelta(days=14) else: - start = self.now - dt.timedelta(days=365) + start = self.timestamp - dt.timedelta(days=365) if end is None: - end = self.now + end = self.timestamp if start.tzinfo is None or start.tzinfo.utcoffset(start) is None: start = pytz.utc.localize(start) @@ -168,7 +172,7 @@ def fetch_price_history( self.randomness[symbol + "_rng"] = rng # The inital price is arbitarly calculated from the first change in price - start_price = 1000 * (self.randomness[symbol][0] + 0.51) + start_price = 1000 * (self.randomness[symbol][0] + 0.501) times = [] current_time = start @@ -218,7 +222,6 @@ def fetch_price_history( results.columns = pd.MultiIndex.from_product([[symbol], results.columns]) results = aggregate_df(results, interval) - return results # TODO: Generate dummy option data @@ -227,7 +230,7 @@ def fetch_option_market_data(self, symbol: str): # This is a placeholder so Trader doesn't crash message = hashlib.sha256() message.update(symbol.encode("utf-8")) - message.update(str(self.now).encode("utf-8")) + message.update(str(self.timestamp).encode("utf-8")) hsh = message.digest() price = int.from_bytes(hsh[:4], "big") / (2 ** 32) price = (price + 1) * 1.5 @@ -267,16 +270,16 @@ def fetch_option_market_data(self, symbol: str): # ------------- Helper methods ------------- # - def _set_now(self, current_datetime: dt.datetime) -> None: + def _set_timestamp(self, current_datetime: dt.datetime) -> None: if ( current_datetime.tzinfo is None or current_datetime.tzinfo.utcoffset(current_datetime) is None ): - self.now = pytz.utc.localize(current_datetime) + self.timestamp = pytz.utc.localize(current_datetime) else: - self.now = current_datetime + self.timestamp = current_datetime def tick(self) -> None: - self.now += interval_to_timedelta(self.poll_interval) + self.timestamp += interval_to_timedelta(self.poll_interval) if not self.trader_main == None: - self.main() + self.main() \ No newline at end of file diff --git a/harvest/api/paper.py b/harvest/api/paper.py index 613943c6..99d00e14 100644 --- a/harvest/api/paper.py +++ b/harvest/api/paper.py @@ -50,11 +50,7 @@ def __init__(self, account_path: str = None, commission_fee=0, streamer=None): self.multiplier = 1 self.commission_fee = commission_fee self.id = 0 - - if streamer is None: - self.streamer = DummyStreamer() - else: - self.streamer = streamer + self.streamer = DummyStreamer() if streamer is None else streamer if account_path: with open(account_path, "r") as f: @@ -117,8 +113,8 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: price = self.streamer.fetch_price_history( sym, self.interval[sym]["interval"], - dt.datetime.now() - dt.timedelta(days=7), - dt.datetime.now(), + self.streamer.get_current_time() - dt.timedelta(days=7), + self.streamer.get_current_time(), )[sym]["close"][-1] qty = ret["quantity"] @@ -157,7 +153,7 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: self.orders.remove(ret) ret = ret_1 ret["status"] = "filled" - ret["filled_time"] = self.streamer.timestamp + ret["filled_time"] = self.streamer.get_current_time() ret["filled_price"] = price else: if pos is None: @@ -175,7 +171,7 @@ def fetch_stock_order_status(self, id: int) -> Dict[str, Any]: self.orders.remove(ret) ret = ret_1 ret["status"] = "filled" - ret["filled_time"] = self.streamer.timestamp + ret["filled_time"] = self.streamer.get_current_time() ret["filled_price"] = price self.equity = self._calc_equity() @@ -237,7 +233,7 @@ def fetch_option_order_status(self, id: int) -> Dict[str, Any]: self.cash -= actual_price self.buying_power -= actual_price ret["status"] = "filled" - ret["filled_time"] = self.streamer.timestamp + ret["filled_time"] = self.streamer.get_current_time() ret["filled_price"] = price debugger.debug(f"After BUY: {self.buying_power}") ret_1 = ret.copy() @@ -259,7 +255,7 @@ def fetch_option_order_status(self, id: int) -> Dict[str, Any]: if pos["quantity"] < 1e-8: self.options.remove(pos) ret["status"] = "filled" - ret["filled_time"] = self.streamer.timestamp + ret["filled_time"] = self.streamer.get_current_time() ret["filled_price"] = price ret_1 = ret.copy() self.orders.remove(ret) diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index c54ba341..dd812304 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -407,6 +407,7 @@ def _update_position_cache(self, df_dict, new=False, option_update=False): equity = net_value + self.account["cash"] self.account["equity"] = equity + self.stock_positions = self.broker.fetch_stock_positions() def _fetch_account_data(self): pos = self.broker.fetch_stock_positions() @@ -442,6 +443,8 @@ def buy(self, symbol: str, quantity: int, in_force: str, extended: bool): limit_price = mark_up(price) total_price = limit_price * quantity + debugger.warning(f"Attempting to buy {quantity} shares of {symbol} at price {price} with price limit {limit_price} and a maximum total price of {total_price}") + if total_price >= buy_power: debugger.error( "Not enough buying power.\n" @@ -471,9 +474,9 @@ def sell(self, symbol: str, quantity: int, in_force: str, extended: bool): return None if symbol_type(symbol) == "OPTION": - price = self.trader.streamer.fetch_option_market_data(symbol)["price"] + price = self.streamer.fetch_option_market_data(symbol)["price"] else: - price = self.trader.storage.load(symbol, self.interval[symbol]["interval"])[ + price = self.storage.load(symbol, self.interval[symbol]["interval"])[ symbol ]["close"][-1] @@ -603,7 +606,7 @@ def __init__(self, streamer=None, storage=None, debug=False): # If streamer is not specified, use YahooStreamer self.streamer = YahooStreamer() if streamer is None else streamer - self.broker = PaperBroker() + self.broker = PaperBroker(streamer=self.streamer) self.storage = ( BaseStorage() if storage is None else storage diff --git a/tests/test_api.py b/tests/test_api.py index b4e16232..2f6a3d0e 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -62,13 +62,13 @@ def test_timeout(self): data["A"]["A"]["close"][-1], t.storage.load("A", Interval.MIN_1)["A"]["close"][-1], ) - # Check if B has been duplicated + # Check if B has been set to 0 self.assertEqual( b_cur["B"]["close"][-1], t.storage.load("B", Interval.MIN_1)["B"]["close"][-2], ) self.assertEqual( - b_cur["B"]["close"][-1], + 0, t.storage.load("B", Interval.MIN_1)["B"]["close"][-1], ) @@ -130,11 +130,7 @@ def test_timeout_cancel(self): def test_exceptions(self): api = API() - try: - api.create_secret("I dont exists") - self.assertTrue(False) - except Exception as e: - self.assertEqual(str(e), "I dont exists was not found.") + self.assertEqual(api.create_secret("I dont exists"), False) try: api.fetch_price_history('A', Interval.MIN_1, now(), now()) diff --git a/tests/test_api_paper.py b/tests/test_api_paper.py index ab719081..78335a91 100644 --- a/tests/test_api_paper.py +++ b/tests/test_api_paper.py @@ -55,7 +55,7 @@ def test_buy(self): dummy = PaperBroker() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) - order = dummy.buy("A", 5, 7) + order = dummy.buy("A", 5, 1e5) self.assertEqual(order["type"], "STOCK") self.assertEqual(order["id"], 0) self.assertEqual(order["symbol"], "A") @@ -117,10 +117,10 @@ def test_order_option_limit(self): ) self.assertEqual(order["type"], "OPTION") self.assertEqual(order["id"], 0) - self.assertEqual(order["symbol"], "A 211106P50001000") + self.assertEqual(order["symbol"], "A 211113P50001000") status = dummy.fetch_option_order_status(order["id"]) - self.assertEqual(status["symbol"], "A 211106P50001000") + self.assertEqual(status["symbol"], "A 211113P50001000") self.assertEqual(status["quantity"], 5) def test_commission(self): From 47c55cac95bf29258ed62122e7c19b6f91321405 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sat, 13 Nov 2021 15:59:26 -0800 Subject: [PATCH 16/20] linted --- harvest/api/_base.py | 2 +- harvest/api/dummy.py | 2 +- harvest/trader/trader.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/harvest/api/_base.py b/harvest/api/_base.py index e63e7952..e0c86b8f 100644 --- a/harvest/api/_base.py +++ b/harvest/api/_base.py @@ -903,4 +903,4 @@ def flush(self): self.block_queue[n] = data self.block_lock.release() self.trader_main(self.block_queue) - self.block_queue = {} \ No newline at end of file + self.block_queue = {} diff --git a/harvest/api/dummy.py b/harvest/api/dummy.py index 7aa078ef..e30a6f63 100644 --- a/harvest/api/dummy.py +++ b/harvest/api/dummy.py @@ -282,4 +282,4 @@ def _set_timestamp(self, current_datetime: dt.datetime) -> None: def tick(self) -> None: self.timestamp += interval_to_timedelta(self.poll_interval) if not self.trader_main == None: - self.main() \ No newline at end of file + self.main() diff --git a/harvest/trader/trader.py b/harvest/trader/trader.py index dd812304..9b1c1e05 100644 --- a/harvest/trader/trader.py +++ b/harvest/trader/trader.py @@ -443,7 +443,9 @@ def buy(self, symbol: str, quantity: int, in_force: str, extended: bool): limit_price = mark_up(price) total_price = limit_price * quantity - debugger.warning(f"Attempting to buy {quantity} shares of {symbol} at price {price} with price limit {limit_price} and a maximum total price of {total_price}") + debugger.warning( + f"Attempting to buy {quantity} shares of {symbol} at price {price} with price limit {limit_price} and a maximum total price of {total_price}" + ) if total_price >= buy_power: debugger.error( From 17df43225f8d5d1b8546fd2f6fb1421faab90f02 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sat, 13 Nov 2021 16:15:28 -0800 Subject: [PATCH 17/20] don't run in github --- examples/em_alpaca.py | 1 + examples/em_kraken.py | 1 + examples/em_polygon.py | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/em_alpaca.py b/examples/em_alpaca.py index 8213b40b..9ee6f518 100644 --- a/examples/em_alpaca.py +++ b/examples/em_alpaca.py @@ -1,3 +1,4 @@ +# HARVEST_SKIP # Builtin imports import logging import datetime as dt diff --git a/examples/em_kraken.py b/examples/em_kraken.py index caf11ac6..909dd88b 100644 --- a/examples/em_kraken.py +++ b/examples/em_kraken.py @@ -1,3 +1,4 @@ +# HARVEST_SKIP # Builtin imports import logging import datetime as dt diff --git a/examples/em_polygon.py b/examples/em_polygon.py index 4f6430f8..95ebcda6 100644 --- a/examples/em_polygon.py +++ b/examples/em_polygon.py @@ -1,3 +1,4 @@ +# HARVEST_SKIP # Builtin imports import logging import datetime as dt From 4eb9c106746cf4408701897ede3c982016d91b34 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sat, 13 Nov 2021 16:22:19 -0800 Subject: [PATCH 18/20] fixed testing on github? --- tests/test_api_paper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_api_paper.py b/tests/test_api_paper.py index 78335a91..c78aa4c4 100644 --- a/tests/test_api_paper.py +++ b/tests/test_api_paper.py @@ -117,10 +117,10 @@ def test_order_option_limit(self): ) self.assertEqual(order["type"], "OPTION") self.assertEqual(order["id"], 0) - self.assertEqual(order["symbol"], "A 211113P50001000") + self.assertEqual(order["symbol"], "A 211114P50001000") status = dummy.fetch_option_order_status(order["id"]) - self.assertEqual(status["symbol"], "A 211113P50001000") + self.assertEqual(status["symbol"], "A 211114P50001000") self.assertEqual(status["quantity"], 5) def test_commission(self): From 8ba82f5cc0c4bf1fed0de8e445b4ed8ba7fdc414 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 14 Nov 2021 18:52:30 -0800 Subject: [PATCH 19/20] fixed broken test --- tests/test_api_paper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api_paper.py b/tests/test_api_paper.py index c78aa4c4..844beced 100644 --- a/tests/test_api_paper.py +++ b/tests/test_api_paper.py @@ -111,7 +111,7 @@ def test_order_option_limit(self): dummy = PaperBroker() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) - exp_date = dt.datetime.now() + dt.timedelta(hours=5) + exp_date = dt.datetime(2020, 11, 14) + dt.timedelta(hours=5) order = dummy.order_option_limit( "buy", "A", 5, 50000, "OPTION", exp_date, 50001 ) From bfc421e2412fa87116cb480efeabdd1fc209ba00 Mon Sep 17 00:00:00 2001 From: Sher Shah Date: Sun, 14 Nov 2021 18:56:58 -0800 Subject: [PATCH 20/20] fixed typo --- tests/test_api_paper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api_paper.py b/tests/test_api_paper.py index 844beced..6b2c9671 100644 --- a/tests/test_api_paper.py +++ b/tests/test_api_paper.py @@ -111,7 +111,7 @@ def test_order_option_limit(self): dummy = PaperBroker() interval = {"A": {"interval": Interval.MIN_1, "aggregations": []}} dummy.setup(interval) - exp_date = dt.datetime(2020, 11, 14) + dt.timedelta(hours=5) + exp_date = dt.datetime(2021, 11, 14) + dt.timedelta(hours=5) order = dummy.order_option_limit( "buy", "A", 5, 50000, "OPTION", exp_date, 50001 )