diff --git a/Blankly/pending_docs.md b/Blankly/PENDING.md similarity index 100% rename from Blankly/pending_docs.md rename to Blankly/PENDING.md diff --git a/Blankly/__init__.py b/Blankly/__init__.py index 77d2f83f..ecd0aaee 100644 --- a/Blankly/__init__.py +++ b/Blankly/__init__.py @@ -16,20 +16,19 @@ along with this program. If not, see . """ -from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro import Coinbase_Pro as Coinbase_Pro -from Blankly.exchanges.interfaces.Binance.Binance import Binance as Binance -from Blankly.exchanges.interfaces.Alpaca.Alpaca import Alpaca as Alpaca -from Blankly.exchanges.interfaces.Paper_Trade.Paper_Trade import PaperTrade as PaperTrade +from Blankly.exchanges.interfaces.coinbase_pro.coinbase_pro import CoinbasePro +from Blankly.exchanges.interfaces.Binance.Binance import Binance +from Blankly.exchanges.interfaces.Alpaca.alpaca import Alpaca +from Blankly.exchanges.interfaces.paper_trade.paper_trade import PaperTrade from Blankly.strategy import Strategy as Strategy from Blankly.strategy import StrategyState as StrategyState -from Blankly.exchanges.managers.ticker_manager import TickerManager as TickerManager -from Blankly.exchanges.managers.orderbook_manager import OrderbookManger as OrderbookManager -from Blankly.exchanges.managers.general_stream_manager import GeneralManager as GeneralManager -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface as Interface +from Blankly.exchanges.managers.ticker_manager import TickerManager +from Blankly.exchanges.managers.orderbook_manager import OrderbookManger +from Blankly.exchanges.managers.general_stream_manager import GeneralManager +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface as Interface from Blankly.strategy.blankly_bot import BlanklyBot import Blankly.utils.utils as utils from Blankly.utils.scheduler import Scheduler import Blankly.indicators as indicators from Blankly.utils import time_builder - diff --git a/Blankly/deployment/server.py b/Blankly/deployment/server.py index bf2f8c72..6d45ea0d 100644 --- a/Blankly/deployment/server.py +++ b/Blankly/deployment/server.py @@ -47,9 +47,9 @@ def init(self, auth_path, preferences_path): def create_portfolio(self, exchange_type, portfolio_name): if exchange_type == "coinbase_pro": - self.__exchanges.append(Blankly.Coinbase_Pro(portfolio_name=portfolio_name, - auth_path=self.__auth_path, - preferences_path=self.__preferences_path)) + self.__exchanges.append(Blankly.CoinbasePro(portfolio_name=portfolio_name, + auth_path=self.__auth_path, + preferences_path=self.__preferences_path)) elif exchange_type == "binance": self.__exchanges.append(Blankly.Binance(portfolio_name=portfolio_name, auth_path=self.__auth_path, diff --git a/Blankly/exchanges/README.md b/Blankly/exchanges/README.md deleted file mode 100644 index 0f221f05..00000000 --- a/Blankly/exchanges/README.md +++ /dev/null @@ -1,39 +0,0 @@ -## Decisions for return types and values of the Interface class - -### get_calls() -- Not relevant - -### get_products() -List for each product: -```json -[ - "currency_id": "BTC-USD", - "base_currency": "BTC", - "quote_currency": "USD", - "base_min_size": "0.01", - "base_max_size": "10000.00" -] -``` - -### get_account(account) -```json -[ - { - "id": "71452118-efc7-4cc4-8780-a5e22d4baa53", - "currency": "BTC", - "balance": "0.0000000000000000", - "available": "0.0000000000000000", - "hold": "0.0000000000000000" - }, - { - ... - } -] -``` -This may be better if users are allowed to search through for a currency because that would remove the need for an ID - -### Orders -------- skipped placement - - -### Cancel order \ No newline at end of file diff --git a/Blankly/exchanges/IExchange.py b/Blankly/exchanges/abc_exchange.py similarity index 97% rename from Blankly/exchanges/IExchange.py rename to Blankly/exchanges/abc_exchange.py index 63dc0421..91dde6e6 100644 --- a/Blankly/exchanges/IExchange.py +++ b/Blankly/exchanges/abc_exchange.py @@ -19,7 +19,7 @@ import abc -class IExchange(abc.ABC): +class ABCExchange(abc.ABC): """ Functions required for easy interaction with the GUI/main """ diff --git a/Blankly/exchanges/IExchange_Websocket.py b/Blankly/exchanges/abc_exchange_websocket.py similarity index 97% rename from Blankly/exchanges/IExchange_Websocket.py rename to Blankly/exchanges/abc_exchange_websocket.py index 90194894..72f5a047 100644 --- a/Blankly/exchanges/IExchange_Websocket.py +++ b/Blankly/exchanges/abc_exchange_websocket.py @@ -19,7 +19,7 @@ import abc -class IExchangeWebsocket(abc.ABC): +class ABCExchangeWebsocket(abc.ABC): """ Each of these functions are required to be implemented for interaction with the ticker manager class. """ diff --git a/Blankly/exchanges/auth/abc_auth.py b/Blankly/exchanges/auth/abc_auth.py index f729b1db..e5597dfe 100644 --- a/Blankly/exchanges/auth/abc_auth.py +++ b/Blankly/exchanges/auth/abc_auth.py @@ -23,7 +23,7 @@ from Blankly.utils.exceptions import AuthError -class AuthInterface(abc.ABC): +class ABCAuth(abc.ABC): def __init__(self, keys_file: str, portfolio_name: str, exchange: str): """ Create a auth interface diff --git a/Blankly/exchanges/exchange.py b/Blankly/exchanges/exchange.py index c3295e8a..05f18bd2 100644 --- a/Blankly/exchanges/exchange.py +++ b/Blankly/exchanges/exchange.py @@ -16,18 +16,18 @@ along with this program. If not, see . """ import Blankly -from Blankly.exchanges.IExchange import IExchange +from Blankly.exchanges.abc_exchange import ABCExchange from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro_Interface import CoinbaseProInterface from Blankly.exchanges.interfaces.Binance.Binance_Interface import BinanceInterface from Blankly.exchanges.auth.auth_factory import AuthFactory from Blankly.exchanges.interfaces.direct_calls_factory import DirectCallsFactory -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface import time import abc -class Exchange(IExchange, abc.ABC): +class Exchange(ABCExchange, abc.ABC): def __init__(self, exchange_type, portfolio_name, keys_path, preferences_path): self.__type = exchange_type # coinbase_pro, binance, alpaca @@ -58,7 +58,7 @@ def construct_interface(self, calls): elif self.__type == "binance": self.Interface = BinanceInterface(self.__type, calls) - def get_interface(self) -> ICurrencyInterface: + def get_interface(self) -> ABCExchangeInterface: """ Get the the authenticated interface for the object. This will provide authenticated API calls. """ diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_cbpro.py b/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_cbpro.py deleted file mode 100644 index 5673b136..00000000 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_cbpro.py +++ /dev/null @@ -1,251 +0,0 @@ -""" - Orderbook websocket feed. - Copyright (c) 2017 Daniel Paquin, modified by Emerson Dove - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. -""" - -from sortedcontainers import SortedDict -from decimal import Decimal -import pickle - -from cbpro.public_client import PublicClient -from cbpro.websocket_client import WebsocketClient - - -class OrderBook(WebsocketClient): - def __init__(self, product_id='BTC-USD', log_to=None): - super(OrderBook, self).__init__(products=product_id) - self._asks = SortedDict() - self._bids = SortedDict() - self._client = PublicClient() - self._sequence = -1 - self._log_to = log_to - if self._log_to: - assert hasattr(self._log_to, 'write') - self._current_ticker = None - - @property - def product_id(self): - """ Currently OrderBook only supports a single product even though it is stored as a list of products. """ - return self.products[0] - - def on_open(self): - self._sequence = -1 - print("-- Subscribed to OrderBook! --\n") - - def on_close(self): - print("\n-- OrderBook Socket Closed! --") - - def reset_book(self): - self._asks = SortedDict() - self._bids = SortedDict() - res = self._client.get_product_order_book(product_id=self.product_id, level=3) - for bid in res['bids']: - self.add({ - 'id': bid[2], - 'side': 'buy', - 'price': Decimal(bid[0]), - 'size': Decimal(bid[1]) - }) - for ask in res['asks']: - self.add({ - 'id': ask[2], - 'side': 'sell', - 'price': Decimal(ask[0]), - 'size': Decimal(ask[1]) - }) - self._sequence = res['sequence'] - - def on_message(self, message): - if self._log_to: - pickle.dump(message, self._log_to) - - sequence = message.get('sequence', -1) - if self._sequence == -1: - self.reset_book() - return - if sequence <= self._sequence: - # ignore older messages (e.g. before order book initialization from getProductOrderBook) - return - elif sequence > self._sequence + 1: - self.on_sequence_gap(self._sequence, sequence) - return - - msg_type = message['type'] - if msg_type == 'open': - self.add(message) - elif msg_type == 'done' and 'price' in message: - self.remove(message) - elif msg_type == 'match': - self.match(message) - self._current_ticker = message - elif msg_type == 'change': - self.change(message) - - self._sequence = sequence - - def on_sequence_gap(self, gap_start, gap_end): - self.reset_book() - print('Error: messages missing ({} - {}). Re-initializing book at sequence.'.format( - gap_start, gap_end, self._sequence)) - - def add(self, order): - order = { - 'id': order.get('order_id') or order['id'], - 'side': order['side'], - 'price': Decimal(order['price']), - 'size': Decimal(order.get('size') or order['remaining_size']) - } - if order['side'] == 'buy': - bids = self.get_bids(order['price']) - if bids is None: - bids = [order] - else: - bids.append(order) - self.set_bids(order['price'], bids) - else: - asks = self.get_asks(order['price']) - if asks is None: - asks = [order] - else: - asks.append(order) - self.set_asks(order['price'], asks) - - def remove(self, order): - price = Decimal(order['price']) - if order['side'] == 'buy': - bids = self.get_bids(price) - if bids is not None: - bids = [o for o in bids if o['id'] != order['order_id']] - if len(bids) > 0: - self.set_bids(price, bids) - else: - self.remove_bids(price) - else: - asks = self.get_asks(price) - if asks is not None: - asks = [o for o in asks if o['id'] != order['order_id']] - if len(asks) > 0: - self.set_asks(price, asks) - else: - self.remove_asks(price) - - def match(self, order): - size = Decimal(order['size']) - price = Decimal(order['price']) - - if order['side'] == 'buy': - bids = self.get_bids(price) - if not bids: - return - assert bids[0]['id'] == order['maker_order_id'] - if bids[0]['size'] == size: - self.set_bids(price, bids[1:]) - else: - bids[0]['size'] -= size - self.set_bids(price, bids) - else: - asks = self.get_asks(price) - if not asks: - return - assert asks[0]['id'] == order['maker_order_id'] - if asks[0]['size'] == size: - self.set_asks(price, asks[1:]) - else: - asks[0]['size'] -= size - self.set_asks(price, asks) - - def change(self, order): - try: - new_size = Decimal(order['new_size']) - except KeyError: - return - - try: - price = Decimal(order['price']) - except KeyError: - return - - if order['side'] == 'buy': - bids = self.get_bids(price) - if bids is None or not any(o['id'] == order['order_id'] for o in bids): - return - index = [b['id'] for b in bids].index(order['order_id']) - bids[index]['size'] = new_size - self.set_bids(price, bids) - else: - asks = self.get_asks(price) - if asks is None or not any(o['id'] == order['order_id'] for o in asks): - return - index = [a['id'] for a in asks].index(order['order_id']) - asks[index]['size'] = new_size - self.set_asks(price, asks) - - tree = self._asks if order['side'] == 'sell' else self._bids - node = tree.get(price) - - if node is None or not any(o['id'] == order['order_id'] for o in node): - return - - def get_current_ticker(self): - return self._current_ticker - - def get_current_book(self): - result = { - 'sequence': self._sequence, - 'asks': [], - 'bids': [], - } - for ask in self._asks: - try: - # There can be a race condition here, where a price point is removed - # between these two ops - this_ask = self._asks[ask] - except KeyError: - continue - for order in this_ask: - result['asks'].append([order['price'], order['size'], order['id']]) - for bid in self._bids: - try: - # There can be a race condition here, where a price point is removed - # between these two ops - this_bid = self._bids[bid] - except KeyError: - continue - - for order in this_bid: - result['bids'].append([order['price'], order['size'], order['id']]) - return result - - def get_ask(self): - return self._asks.peekitem(0)[0] - - def get_asks(self, price): - return self._asks.get(price) - - def remove_asks(self, price): - del self._asks[price] - - def set_asks(self, price, asks): - self._asks[price] = asks - - def get_bid(self): - return self._bids.peekitem(-1)[0] - - def get_bids(self, price): - return self._bids.get(price) - - def remove_bids(self, price): - del self._bids[price] - - def set_bids(self, price, bids): - self._bids[price] = bids diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_websocket.py b/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_websocket.py deleted file mode 100644 index a5ae51df..00000000 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/orderbook_websocket.py +++ /dev/null @@ -1,192 +0,0 @@ -""" - Coinbase Pro orderbook websocket feed. - Copyright (C) 2021 Emerson Dove - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -""" -import threading -import json -import ssl -import time -import traceback -import Blankly -import collections -from Blankly.exchanges.IExchange_Websocket import IExchangeWebsocket - -from websocket import create_connection - -""" ---- DEPRECATED FILE. All orderbook management now goes through the Coinbase Pro Websocket file. ----- -""" - - -def create_websocket_connection(id, url): - ws = create_connection(url, sslopt={"cert_reqs": ssl.CERT_NONE}) - request = """{ - "type": "subscribe", - "product_ids": [ - \"""" + id + """\" - ], - "channels": [ - "level2" - ] - }""" - ws.send(request) - return ws - - -class OrderBook(IExchangeWebsocket): - def __init__(self, currency_id, WEBSOCKET_URL="wss://ws-feed.pro.coinbase.com"): - """ - Create and initialize the orderbook connection - Args: - currency_id: Currency to listen on such as "BTC-USD" - WEBSOCKET_URL: Default websocket URL feed. - """ - self.__id = currency_id - - self.URL = WEBSOCKET_URL - self.ws = None - self.__response = None - self.__most_recent_tick = None - self.__most_recent_time = None - self.__callbacks = [] - self.__snapshot_callbacks = [] - - # Load preferences and create the buffers - self.__preferences = Blankly.utils.load_user_preferences() - buffer_size = self.__preferences["settings"]["websocket_buffer_size"] - self.__orderbook_feed = collections.deque(maxlen=buffer_size) - self.__time_feed = collections.deque(maxlen=buffer_size) - - # Create the snapshot load - self.__snapshot = None - - # Start the websocket - self.start_websocket() - - # This could be made static with some changes, would make the code in the loop cleaner - def start_websocket(self): - """ - Restart websocket if it was asked to stop. - """ - if self.ws is None: - self.ws = create_websocket_connection(self.__id, self.URL) - self.__response = self.ws.recv() - thread = threading.Thread(target=self.read_websocket) - thread.start() - else: - if self.ws.connected: - print("Already running...") - pass - else: - # Use recursion to restart, continue appending to time feed and orderbook feed - self.ws = None - self.start_websocket() - - def read_websocket(self): - # This is unique because coinbase first sends the entire orderbook to use - received_string = json.loads(self.ws.recv()) - if received_string['type'] == 'snapshot': - self.__snapshot = received_string - try: - for i in self.__snapshot_callbacks: - i(received_string) - except: - traceback.print_exc() - - # TODO port this to "WebSocketApp" found in the websockets documentation - while self.ws.connected: - # In case the user closes while its reading from the websocket - persist_connected = self.ws.connected - try: - received_string = self.ws.recv() - received = json.loads(received_string) - self.__most_recent_time = Blankly.utils.epoch_from_ISO8601(received['time']) - received['time'] = self.__most_recent_time - self.__orderbook_feed.append(received) - self.__most_recent_tick = received - self.__time_feed.append(self.__most_recent_time) - - # Manage price events and fire for each manager attached - try: - for i in range(len(self.__callbacks)): - self.__callbacks[i](received) - except Exception: - traceback.print_exc() - - except Exception as e: - if persist_connected: - traceback.print_exc() - continue - else: - print(traceback.format_exc()) - print("Error reading orderbook for " + self.__id + ": attempting to re-initialize") - # Give a delay so this doesn't eat up from the main thread if it takes many tries to initialize - time.sleep(2) - self.ws.close() - self.ws = create_websocket_connection(self.__id, self.URL) - # Update response - self.__response = self.ws.recv() - # This allows us to put initialization at the top of the function - self.read_websocket() - break - - """ Required in manager """ - def is_websocket_open(self): - return self.ws.connected - - def get_currency_id(self): - return self.__id - - """ Required in manager """ - def append_callback(self, obj): - self.__callbacks.append(obj) - - def append_snapshot_callback(self, obj): - self.__snapshot_callbacks.append(obj) - - """ Define a variable each time so there is no array manipulation """ - """ Required in manager """ - def get_most_recent_tick(self): - return self.__most_recent_tick - - """ Required in manager """ - def get_most_recent_time(self): - return self.__most_recent_time - - """ Required in manager """ - def get_time_feed(self): - return list(self.__time_feed) - - """ Parallel with time feed """ - """ Required in manager """ - def get_feed(self): - return list(self.__orderbook_feed) - - """ Required in manager """ - def get_response(self): - return self.__response - - """ Required in manager """ - def close_websocket(self): - if self.ws.connected: - self.ws.close() - else: - print("Websocket for " + self.__id + " is already closed") - - """ Required in manager """ - def restart_ticker(self): - self.start_websocket() - diff --git a/Blankly/exchanges/interfaces/abc_currency_interface.py b/Blankly/exchanges/interfaces/abc_exchange_interface.py similarity index 99% rename from Blankly/exchanges/interfaces/abc_currency_interface.py rename to Blankly/exchanges/interfaces/abc_exchange_interface.py index ae754e88..8c03e7ea 100644 --- a/Blankly/exchanges/interfaces/abc_currency_interface.py +++ b/Blankly/exchanges/interfaces/abc_exchange_interface.py @@ -24,7 +24,7 @@ from typing import Union -class ICurrencyInterface(abc.ABC): +class ABCExchangeInterface(abc.ABC): @abc.abstractmethod def __init__(self, exchange_name, authenticated_API): """ @@ -186,7 +186,7 @@ def get_fees(self) -> dict: """ Coinbase Pro: get_account_history - Binance: + binance: get_deposit_history get_withdraw_history diff --git a/Blankly/exchanges/interfaces/Alpaca/__init__.py b/Blankly/exchanges/interfaces/alpaca/__init__.py similarity index 100% rename from Blankly/exchanges/interfaces/Alpaca/__init__.py rename to Blankly/exchanges/interfaces/alpaca/__init__.py diff --git a/Blankly/exchanges/interfaces/Alpaca/Alpaca.py b/Blankly/exchanges/interfaces/alpaca/alpaca.py similarity index 96% rename from Blankly/exchanges/interfaces/Alpaca/Alpaca.py rename to Blankly/exchanges/interfaces/alpaca/alpaca.py index be4ca1ba..93bfb811 100644 --- a/Blankly/exchanges/interfaces/Alpaca/Alpaca.py +++ b/Blankly/exchanges/interfaces/alpaca/alpaca.py @@ -1,5 +1,5 @@ """ - Alpaca exchange definitions and setup + alpaca exchange definitions and setup Copyright (C) 2021 Arun Annamalai, Emerson Dove, Brandon Fan This program is free software: you can redistribute it and/or modify diff --git a/Blankly/exchanges/interfaces/Alpaca/Alpaca_API.py b/Blankly/exchanges/interfaces/alpaca/alpaca_api.py similarity index 78% rename from Blankly/exchanges/interfaces/Alpaca/Alpaca_API.py rename to Blankly/exchanges/interfaces/alpaca/alpaca_api.py index 8117d059..6f5c8047 100644 --- a/Blankly/exchanges/interfaces/Alpaca/Alpaca_API.py +++ b/Blankly/exchanges/interfaces/alpaca/alpaca_api.py @@ -1,4 +1,4 @@ -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth import alpaca_trade_api import os @@ -7,7 +7,7 @@ APCA_API_PAPER_URL = "https://paper-api.alpaca.markets" -def create_alpaca_client(auth: AuthInterface, sandbox_mode=True): +def create_alpaca_client(auth: ABCAuth, sandbox_mode=True): if sandbox_mode: api_url = APCA_API_PAPER_URL else: @@ -17,7 +17,7 @@ def create_alpaca_client(auth: AuthInterface, sandbox_mode=True): class API: - def __init__(self, auth: AuthInterface, paper_trading=True): + def __init__(self, auth: ABCAuth, paper_trading=True): if paper_trading: self.__api_url = APCA_API_PAPER_URL else: diff --git a/Blankly/exchanges/interfaces/Alpaca/alpaca_auth.py b/Blankly/exchanges/interfaces/alpaca/alpaca_auth.py similarity index 88% rename from Blankly/exchanges/interfaces/Alpaca/alpaca_auth.py rename to Blankly/exchanges/interfaces/alpaca/alpaca_auth.py index 2457895d..ecf9bf49 100644 --- a/Blankly/exchanges/interfaces/Alpaca/alpaca_auth.py +++ b/Blankly/exchanges/interfaces/alpaca/alpaca_auth.py @@ -1,5 +1,5 @@ """ - Alpaca authentication base class + alpaca authentication base class Copyright (C) 2021 Arun Annamalai, Emerson Dove This program is free software: you can redistribute it and/or modify @@ -17,10 +17,10 @@ """ -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth -class AlpacaAuth(AuthInterface): +class AlpacaAuth(ABCAuth): def __init__(self, keys_file, portfolio_name): super().__init__(keys_file, portfolio_name, 'alpaca') needed_keys = ['API_KEY', 'API_SECRET'] diff --git a/Blankly/exchanges/interfaces/Alpaca/alpaca_fixes.md b/Blankly/exchanges/interfaces/alpaca/alpaca_fixes.md similarity index 100% rename from Blankly/exchanges/interfaces/Alpaca/alpaca_fixes.md rename to Blankly/exchanges/interfaces/alpaca/alpaca_fixes.md diff --git a/Blankly/exchanges/interfaces/Alpaca/alpaca_api_interface.py b/Blankly/exchanges/interfaces/alpaca/alpaca_interface.py similarity index 95% rename from Blankly/exchanges/interfaces/Alpaca/alpaca_api_interface.py rename to Blankly/exchanges/interfaces/alpaca/alpaca_interface.py index 6bcfc50d..42d155c2 100644 --- a/Blankly/exchanges/interfaces/Alpaca/alpaca_api_interface.py +++ b/Blankly/exchanges/interfaces/alpaca/alpaca_interface.py @@ -1,5 +1,5 @@ """ - Alpaca API Interface Definition + alpaca API Interface Definition Copyright (C) 2021 Arun Annamalai This program is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ from alpaca_trade_api.rest import TimeFrame from Blankly.utils import utils as utils -from Blankly.exchanges.interfaces.Alpaca.Alpaca_API import API -from Blankly.exchanges.interfaces.currency_Interface import CurrencyInterface +from Blankly.exchanges.interfaces.Alpaca.alpaca_api import API +from Blankly.exchanges.interfaces.exchange_interface import ExchangeInterface import alpaca_trade_api from Blankly.exchanges.orders.limit_order import LimitOrder @@ -34,7 +34,7 @@ NY = 'America/New_York' -class AlpacaInterface(CurrencyInterface): +class AlpacaInterface(ExchangeInterface): def __init__(self, authenticated_API: API, preferences_path: str): super().__init__('alpaca', authenticated_API, preferences_path) assert isinstance(self.calls, alpaca_trade_api.REST) @@ -46,7 +46,7 @@ def init_exchange(self): if account_info['account_blocked']: warnings.warn('Your alpaca account is indicated as blocked for trading....') except KeyError: - raise LookupError("Alpaca API call failed") + raise LookupError("alpaca API call failed") self.__exchange_properties = { "maker_fee_rate": 0, @@ -207,7 +207,7 @@ def get_product_history(self, product_id: str, epoch_start: dt, epoch_stop: dt, supported_multiples = [60, 3600, 86400] if resolution < 60: - raise ValueError("Alpaca does not support sub-minute candlesticks") + raise ValueError("alpaca does not support sub-minute candlesticks") found_multiple = -1 for multiple in supported_multiples: @@ -215,7 +215,7 @@ def get_product_history(self, product_id: str, epoch_start: dt, epoch_stop: dt, found_multiple = multiple break if found_multiple < 0: - raise ValueError("Alpaca currently does not support this specific resolution, please make the resolution a multiple of 1 minute, 1 hour or 1 day") + raise ValueError("alpaca currently does not support this specific resolution, please make the resolution a multiple of 1 minute, 1 hour or 1 day") if found_multiple == 60: time_interval = TimeFrame.Minute @@ -233,7 +233,7 @@ def get_product_history(self, product_id: str, epoch_start: dt, epoch_stop: dt, return self.calls.get_bars(product_id, time_interval, epoch_start_str, epoch_stop_str,adjustment='raw').df.iloc[::row_divisor, :] - # TODO: tbh not sure how this one works or if it applies to Alpaca + # TODO: tbh not sure how this one works or if it applies to alpaca def get_market_limits(self, product_id): assert isinstance(self.calls, alpaca_trade_api.REST) pass diff --git a/Blankly/exchanges/interfaces/Binance/__init__.py b/Blankly/exchanges/interfaces/binance/__init__.py similarity index 100% rename from Blankly/exchanges/interfaces/Binance/__init__.py rename to Blankly/exchanges/interfaces/binance/__init__.py diff --git a/Blankly/exchanges/interfaces/Binance/Binance.py b/Blankly/exchanges/interfaces/binance/binance.py similarity index 97% rename from Blankly/exchanges/interfaces/Binance/Binance.py rename to Blankly/exchanges/interfaces/binance/binance.py index 4830cb7f..df7f8db8 100644 --- a/Blankly/exchanges/interfaces/Binance/Binance.py +++ b/Blankly/exchanges/interfaces/binance/binance.py @@ -1,5 +1,5 @@ """ - Binance exchange definitions and setup + binance exchange definitions and setup Copyright (C) 2021 Emerson Dove This program is free software: you can redistribute it and/or modify diff --git a/Blankly/exchanges/interfaces/Binance/Binance_API.py b/Blankly/exchanges/interfaces/binance/binance_api.py similarity index 99% rename from Blankly/exchanges/interfaces/Binance/Binance_API.py rename to Blankly/exchanges/interfaces/binance/binance_api.py index f44b8373..67d2135a 100644 --- a/Blankly/exchanges/interfaces/Binance/Binance_API.py +++ b/Blankly/exchanges/interfaces/binance/binance_api.py @@ -1,5 +1,5 @@ """ - Unused Binance API calls. + Unused binance API calls. Copyright (C) 2021 Emerson Dove This program is free software: you can redistribute it and/or modify diff --git a/Blankly/exchanges/interfaces/Binance/binance_auth.py b/Blankly/exchanges/interfaces/binance/binance_auth.py similarity index 87% rename from Blankly/exchanges/interfaces/Binance/binance_auth.py rename to Blankly/exchanges/interfaces/binance/binance_auth.py index fbba056e..ea2d12ae 100644 --- a/Blankly/exchanges/interfaces/Binance/binance_auth.py +++ b/Blankly/exchanges/interfaces/binance/binance_auth.py @@ -1,5 +1,5 @@ """ - Binance authentication base class + binance authentication base class Copyright (C) 2021 Arun Annamalai, Emerson Dove This program is free software: you can redistribute it and/or modify @@ -17,10 +17,10 @@ """ -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth -class BinanceAuth(AuthInterface): +class BinanceAuth(ABCAuth): def __init__(self, keys_file, portfolio_name): super().__init__(keys_file, portfolio_name, 'binance') needed_keys = ['API_KEY', 'API_SECRET'] diff --git a/Blankly/exchanges/interfaces/Binance/Binance_Interface.py b/Blankly/exchanges/interfaces/binance/binance_interface.py similarity index 98% rename from Blankly/exchanges/interfaces/Binance/Binance_Interface.py rename to Blankly/exchanges/interfaces/binance/binance_interface.py index 873210e8..2c87dd6d 100644 --- a/Blankly/exchanges/interfaces/Binance/Binance_Interface.py +++ b/Blankly/exchanges/interfaces/binance/binance_interface.py @@ -26,10 +26,10 @@ import Blankly.utils.utils as utils from Blankly.exchanges.orders.limit_order import LimitOrder from Blankly.exchanges.orders.market_order import MarketOrder -from Blankly.exchanges.interfaces.currency_Interface import CurrencyInterface +from Blankly.exchanges.interfaces.exchange_interface import ExchangeInterface -class BinanceInterface(CurrencyInterface): +class BinanceInterface(ExchangeInterface): def __init__(self, exchange_name, authenticated_API): super().__init__(exchange_name, authenticated_API) @@ -162,7 +162,7 @@ def get_account(self, currency=None) -> utils.AttributeDict: These arguments are mutually exclusive Coinbase Pro: get_account - Binance: get_account["balances"] + binance: get_account["balances"] """ currency = super().get_account(currency=currency) @@ -221,7 +221,7 @@ def get_account(self, currency=None) -> utils.AttributeDict: else: raise LookupError("Currency not found") - # Binance only returns things you own, so extract those - scan and add that to the array. + # binance only returns things you own, so extract those - scan and add that to the array. # We can fill it to a balance of zero later owned_assets = [] for i in accounts: @@ -540,7 +540,7 @@ def get_order(self, currency_id, order_id) -> dict: """ Coinbase Pro: get_fees - Binance: get_trade_fee + binance: get_trade_fee """ def get_fees(self) -> dict: @@ -568,7 +568,7 @@ def get_fees(self) -> dict: ] } """ - # TODO: make sure this supports with Binance Coin (BNB) discount + # TODO: make sure this supports with binance Coin (BNB) discount account = self.calls.get_account() # Get rid of the stuff we really don't need this time account.pop('canTrade') @@ -583,7 +583,7 @@ def get_fees(self) -> dict: """ Coinbase Pro: get_account_history - Binance: + binance: get_deposit_history get_withdraw_history @@ -687,7 +687,7 @@ def get_product_history(self, product_id, epoch_start, epoch_stop, resolution): """ Coinbase Pro: Get Currencies - Binance: get_products + binance: get_products """ def get_market_limits(self, product_id): diff --git a/Blankly/exchanges/interfaces/Binance/Binance_Websocket.py b/Blankly/exchanges/interfaces/binance/binance_websocket.py similarity index 97% rename from Blankly/exchanges/interfaces/Binance/Binance_Websocket.py rename to Blankly/exchanges/interfaces/binance/binance_websocket.py index e9f5949c..41f2109a 100644 --- a/Blankly/exchanges/interfaces/Binance/Binance_Websocket.py +++ b/Blankly/exchanges/interfaces/binance/binance_websocket.py @@ -1,5 +1,5 @@ """ - Binance ticker class. + binance ticker class. Copyright (C) 2021 Emerson Dove This program is free software: you can redistribute it and/or modify @@ -17,7 +17,7 @@ """ import websocket -from Blankly.exchanges.IExchange_Websocket import IExchangeWebsocket +from Blankly.exchanges.abc_exchange_websocket import ABCExchangeWebsocket import Blankly.exchanges.interfaces.Binance.websocket_utils as websocket_utils import collections import json @@ -26,7 +26,7 @@ import traceback -class Tickers(IExchangeWebsocket): +class Tickers(ABCExchangeWebsocket): def __init__(self, symbol, stream, log=None, initially_stopped=False, WEBSOCKET_URL="wss://stream.binance.com:9443/ws"): """ diff --git a/Blankly/exchanges/interfaces/Binance/websocket_utils.py b/Blankly/exchanges/interfaces/binance/binance_websocket_utils.py similarity index 98% rename from Blankly/exchanges/interfaces/Binance/websocket_utils.py rename to Blankly/exchanges/interfaces/binance/binance_websocket_utils.py index 7beb7f0a..f33e9eb3 100644 --- a/Blankly/exchanges/interfaces/Binance/websocket_utils.py +++ b/Blankly/exchanges/interfaces/binance/binance_websocket_utils.py @@ -1,5 +1,5 @@ """ - Websocket feeds need to be modular due to the subscription methods, this provides dynamic management for Binance. + Websocket feeds need to be modular due to the subscription methods, this provides dynamic management for binance. Copyright (C) 2021 Emerson Dove This program is free software: you can redistribute it and/or modify diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/__init__.py b/Blankly/exchanges/interfaces/coinbase_pro/__init__.py similarity index 100% rename from Blankly/exchanges/interfaces/Coinbase_Pro/__init__.py rename to Blankly/exchanges/interfaces/coinbase_pro/__init__.py diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro.py similarity index 97% rename from Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro.py index fbb77160..bf4677ad 100644 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro.py +++ b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro.py @@ -21,7 +21,7 @@ from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro_API import API as Coinbase_Pro_API -class Coinbase_Pro(Exchange): +class CoinbasePro(Exchange): def __init__(self, portfolio_name=None, keys_path="keys.json", settings_path=None): # Giving the preferences path as none allows us to create a default Exchange.__init__(self, "coinbase_pro", portfolio_name, keys_path, settings_path) @@ -48,7 +48,7 @@ def get_direct_calls(self) -> Coinbase_Pro_API: return self.calls """ - GUI Testing Functions | These only exist in the Coinbase_Pro class: + GUI Testing Functions | These only exist in the coinbase_pro class: """ def get_indicators(self): return self.calls.get_fees() diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_API.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_api.py similarity index 99% rename from Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_API.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_api.py index 27adca6d..bed41d54 100644 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_API.py +++ b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_api.py @@ -25,12 +25,12 @@ # Create custom authentication for Exchange -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth class CoinbaseExchangeAuth(AuthBase): # Provided by CBPro: https://docs.pro.coinbase.com/#signing-a-message - def __init__(self, cb_auth: AuthInterface): + def __init__(self, cb_auth: ABCAuth): self.api_key = cb_auth.keys['API_KEY'] self.secret_key = cb_auth.keys['API_SECRET'] self.passphrase = cb_auth.keys['API_PASS'] @@ -61,7 +61,7 @@ def get_auth_headers(timestamp, message, api_key, secret_key, passphrase): class API: - def __init__(self, cb_auth: AuthInterface, API_URL='https://api.pro.coinbase.com/'): + def __init__(self, cb_auth: ABCAuth, API_URL='https://api.pro.coinbase.com/'): self.__auth = CoinbaseExchangeAuth(cb_auth) self.__api_url = API_URL self.session = requests.Session() diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/coinbase_pro_auth.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_auth.py similarity index 91% rename from Blankly/exchanges/interfaces/Coinbase_Pro/coinbase_pro_auth.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_auth.py index 316f95ed..d8911c70 100644 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/coinbase_pro_auth.py +++ b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_auth.py @@ -17,10 +17,10 @@ """ -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth -class CoinbaseAuth(AuthInterface): +class CoinbaseProAuth(ABCAuth): def __init__(self, keys_file, portfolio_name): super().__init__(keys_file, portfolio_name, 'coinbase_pro') needed_keys = ['API_KEY', 'API_SECRET', 'API_PASS'] diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Interface.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py similarity index 99% rename from Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Interface.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py index 7799a3f4..dd5df9d1 100644 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Interface.py +++ b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_interface.py @@ -30,10 +30,10 @@ from Blankly.exchanges.orders.stop_limit import StopLimit -from Blankly.exchanges.interfaces.currency_Interface import CurrencyInterface +from Blankly.exchanges.interfaces.exchange_interface import ExchangeInterface -class CoinbaseProInterface(CurrencyInterface): +class CoinbaseProInterface(ExchangeInterface): def __init__(self, exchange_name, authenticated_API): super().__init__(exchange_name, authenticated_API) @@ -395,7 +395,7 @@ def get_order(self, currency_id, order_id) -> dict: """ Coinbase Pro: get_fees - Binance: get_trade_fee + binance: get_trade_fee """ def get_fees(self) -> dict: @@ -412,7 +412,7 @@ def get_fees(self) -> dict: """ Coinbase Pro: get_account_history - Binance: + binance: get_deposit_history get_withdraw_history @@ -475,7 +475,7 @@ def get_product_history(self, product_id, epoch_start, epoch_stop, resolution): """ Coinbase Pro: Get Currencies - Binance: get_products + binance: get_products """ def get_market_limits(self, product_id): diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Utils.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_utils.py similarity index 100% rename from Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Utils.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_utils.py diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Websocket.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_websocket.py similarity index 98% rename from Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Websocket.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_websocket.py index 4a5be652..3489dbfb 100644 --- a/Blankly/exchanges/interfaces/Coinbase_Pro/Coinbase_Pro_Websocket.py +++ b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_websocket.py @@ -22,7 +22,7 @@ import ssl import time import traceback -from Blankly.exchanges.IExchange_Websocket import IExchangeWebsocket +from Blankly.exchanges.abc_exchange_websocket import ABCExchangeWebsocket import Blankly.exchanges.interfaces.Coinbase_Pro.websocket_utils as websocket_utils import collections @@ -52,7 +52,7 @@ def create_ticker_connection(id, url, channel): # ] -class Tickers(IExchangeWebsocket): +class Tickers(ABCExchangeWebsocket): def __init__(self, currency_id, stream, log=None, pre_event_callback=None, initially_stopped=False, WEBSOCKET_URL="wss://ws-feed.pro.coinbase.com"): """ diff --git a/Blankly/exchanges/interfaces/Coinbase_Pro/websocket_utils.py b/Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_websocket_utils.py similarity index 100% rename from Blankly/exchanges/interfaces/Coinbase_Pro/websocket_utils.py rename to Blankly/exchanges/interfaces/coinbase_pro/coinbase_pro_websocket_utils.py diff --git a/Blankly/exchanges/interfaces/direct_calls_factory.py b/Blankly/exchanges/interfaces/direct_calls_factory.py index 3c15cfe6..9a7bf8dd 100644 --- a/Blankly/exchanges/interfaces/direct_calls_factory.py +++ b/Blankly/exchanges/interfaces/direct_calls_factory.py @@ -17,11 +17,11 @@ """ -from Blankly.exchanges.auth.abc_auth import AuthInterface +from Blankly.exchanges.auth.abc_auth import ABCAuth from Blankly.exchanges.interfaces.Alpaca.alpaca_api_interface import AlpacaInterface from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro_API import API as Coinbase_Pro_API from binance.client import Client -from Blankly.exchanges.interfaces.Alpaca.Alpaca_API import create_alpaca_client +from Blankly.exchanges.interfaces.Alpaca.alpaca_api import create_alpaca_client from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro_Interface import CoinbaseProInterface from Blankly.exchanges.interfaces.Binance.Binance_Interface import BinanceInterface import Blankly.utils.utils as utils @@ -29,7 +29,7 @@ class DirectCallsFactory: @staticmethod - def create(exchange_name: str, auth: AuthInterface, preferences_path: str = None): + def create(exchange_name: str, auth: ABCAuth, preferences_path: str = None): preferences = utils.load_user_preferences(preferences_path) if exchange_name == 'coinbase_pro': if preferences["settings"]["use_sandbox"]: diff --git a/Blankly/exchanges/interfaces/currency_Interface.py b/Blankly/exchanges/interfaces/exchange_interface.py similarity index 97% rename from Blankly/exchanges/interfaces/currency_Interface.py rename to Blankly/exchanges/interfaces/exchange_interface.py index 0a456bec..8520d79e 100644 --- a/Blankly/exchanges/interfaces/currency_Interface.py +++ b/Blankly/exchanges/interfaces/exchange_interface.py @@ -18,13 +18,13 @@ import Blankly.utils.utils as utils from Blankly.utils.time_builder import time_interval_to_seconds -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface import abc import time # TODO: need to add a cancel all orders function -class CurrencyInterface(ICurrencyInterface, abc.ABC): +class ExchangeInterface(ABCExchangeInterface, abc.ABC): def __init__(self, exchange_name, authenticated_API, preferences_path=None): self.exchange_name = exchange_name self.calls = authenticated_API @@ -178,7 +178,7 @@ def get_account(self, currency=None): currency (Optional): Filter by particular currency Coinbase Pro: get_account - Binance: get_account["balances"] + binance: get_account["balances"] """ if currency is not None: diff --git a/Blankly/exchanges/interfaces/Paper_Trade/__init__.py b/Blankly/exchanges/interfaces/paper_trade/__init__.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/__init__.py rename to Blankly/exchanges/interfaces/paper_trade/__init__.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/backtest_controller.py b/Blankly/exchanges/interfaces/paper_trade/backtest_controller.py similarity index 98% rename from Blankly/exchanges/interfaces/Paper_Trade/backtest_controller.py rename to Blankly/exchanges/interfaces/paper_trade/backtest_controller.py index 3c947466..b807cf96 100644 --- a/Blankly/exchanges/interfaces/Paper_Trade/backtest_controller.py +++ b/Blankly/exchanges/interfaces/paper_trade/backtest_controller.py @@ -17,12 +17,12 @@ """ -from Blankly.exchanges.interfaces.Paper_Trade.Paper_Trade import PaperTrade -from Blankly.exchanges.interfaces.Paper_Trade.Paper_Trade_Interface import PaperTradeInterface +from Blankly.exchanges.interfaces.paper_trade.paper_trade import PaperTrade +from Blankly.exchanges.interfaces.paper_trade.paper_trade_interface import PaperTradeInterface from Blankly.utils.time_builder import time_interval_to_seconds from Blankly.utils.utils import load_backtest_preferences, write_backtest_preferences, update_progress -import Blankly.exchanges.interfaces.Paper_Trade.metrics as metrics -from Blankly.exchanges.interfaces.Paper_Trade.backtest_result import BacktestResult +import Blankly.exchanges.interfaces.paper_trade.metrics as metrics +from Blankly.exchanges.interfaces.paper_trade.backtest_result import BacktestResult import typing import pandas as pd diff --git a/Blankly/exchanges/interfaces/Paper_Trade/backtest_result.py b/Blankly/exchanges/interfaces/paper_trade/backtest_result.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/backtest_result.py rename to Blankly/exchanges/interfaces/paper_trade/backtest_result.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/backtesting_wrapper.py b/Blankly/exchanges/interfaces/paper_trade/backtesting_wrapper.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/backtesting_wrapper.py rename to Blankly/exchanges/interfaces/paper_trade/backtesting_wrapper.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/local_account/__init__.py b/Blankly/exchanges/interfaces/paper_trade/local_account/__init__.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/local_account/__init__.py rename to Blankly/exchanges/interfaces/paper_trade/local_account/__init__.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/local_account/local_account.py b/Blankly/exchanges/interfaces/paper_trade/local_account/local_account.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/local_account/local_account.py rename to Blankly/exchanges/interfaces/paper_trade/local_account/local_account.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/local_account/trade_local.py b/Blankly/exchanges/interfaces/paper_trade/local_account/trade_local.py similarity index 98% rename from Blankly/exchanges/interfaces/Paper_Trade/local_account/trade_local.py rename to Blankly/exchanges/interfaces/paper_trade/local_account/trade_local.py index 89fd18e0..5033b0e0 100644 --- a/Blankly/exchanges/interfaces/Paper_Trade/local_account/trade_local.py +++ b/Blankly/exchanges/interfaces/paper_trade/local_account/trade_local.py @@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . """ -import Blankly.exchanges.interfaces.Paper_Trade.local_account.local_account as local_account +import Blankly.exchanges.interfaces.paper_trade.local_account.local_account as local_account import Blankly.utils.utils as utils from Blankly.utils.exceptions import InvalidOrder diff --git a/Blankly/exchanges/interfaces/Paper_Trade/metrics.py b/Blankly/exchanges/interfaces/paper_trade/metrics.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/metrics.py rename to Blankly/exchanges/interfaces/paper_trade/metrics.py diff --git a/Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade.py b/Blankly/exchanges/interfaces/paper_trade/paper_trade.py similarity index 96% rename from Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade.py rename to Blankly/exchanges/interfaces/paper_trade/paper_trade.py index 356a8f5a..3ade0ac9 100644 --- a/Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade.py +++ b/Blankly/exchanges/interfaces/paper_trade/paper_trade.py @@ -17,7 +17,7 @@ """ -from Blankly.exchanges.interfaces.Paper_Trade.Paper_Trade_Interface import PaperTradeInterface +from Blankly.exchanges.interfaces.paper_trade.paper_trade_interface import PaperTradeInterface from Blankly.exchanges.exchange import Exchange diff --git a/Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade_Interface.py b/Blankly/exchanges/interfaces/paper_trade/paper_trade_interface.py similarity index 97% rename from Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade_Interface.py rename to Blankly/exchanges/interfaces/paper_trade/paper_trade_interface.py index bfaea9a8..28dd8ac6 100644 --- a/Blankly/exchanges/interfaces/Paper_Trade/Paper_Trade_Interface.py +++ b/Blankly/exchanges/interfaces/paper_trade/paper_trade_interface.py @@ -17,16 +17,16 @@ """ -from Blankly.exchanges.interfaces.currency_Interface import CurrencyInterface -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface -from Blankly.exchanges.interfaces.Paper_Trade.backtesting_wrapper import BacktestingWrapper +from Blankly.exchanges.interfaces.exchange_interface import ExchangeInterface +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface +from Blankly.exchanges.interfaces.paper_trade.backtesting_wrapper import BacktestingWrapper from Blankly.utils.exceptions import InvalidOrder from Blankly.utils.exceptions import APIException -import Blankly.exchanges.interfaces.Paper_Trade.local_account.trade_local as trade_local -import Blankly.exchanges.interfaces.Paper_Trade.utils as paper_trade +import Blankly.exchanges.interfaces.paper_trade.local_account.trade_local as trade_local +import Blankly.exchanges.interfaces.paper_trade.utils as paper_trade import Blankly.utils.utils as utils @@ -39,8 +39,8 @@ import traceback -class PaperTradeInterface(CurrencyInterface, BacktestingWrapper): - def __init__(self, derived_interface: ICurrencyInterface, initial_account_values: dict = None): +class PaperTradeInterface(ExchangeInterface, BacktestingWrapper): + def __init__(self, derived_interface: ABCExchangeInterface, initial_account_values: dict = None): self.paper_trade_orders = [] self.get_products_cache = None @@ -54,7 +54,7 @@ def __init__(self, derived_interface: ICurrencyInterface, initial_account_values self.__thread = None # Set the type of the paper trade exchange to be the same as whichever interface its derived from - CurrencyInterface.__init__(self, derived_interface.get_exchange_type(), derived_interface) + ExchangeInterface.__init__(self, derived_interface.get_exchange_type(), derived_interface) BacktestingWrapper.__init__(self) # Write in the accounts to our local account. This involves getting the values directly from the exchange diff --git a/Blankly/exchanges/interfaces/Paper_Trade/utils.py b/Blankly/exchanges/interfaces/paper_trade/utils.py similarity index 100% rename from Blankly/exchanges/interfaces/Paper_Trade/utils.py rename to Blankly/exchanges/interfaces/paper_trade/utils.py diff --git a/Blankly/exchanges/managers/orderbook_manager.py b/Blankly/exchanges/managers/orderbook_manager.py index 8178cd30..65a92c30 100644 --- a/Blankly/exchanges/managers/orderbook_manager.py +++ b/Blankly/exchanges/managers/orderbook_manager.py @@ -122,7 +122,7 @@ def create_orderbook(self, callback, currency_id=None, override_exchange=None, i websocket = Binance_Orderbook(specific_currency_id, "depth", initially_stopped=initially_stopped) websocket.append_callback(self.binance_update) - # Binance returns the keys in all UPPER so the books should be created based on response + # binance returns the keys in all UPPER so the books should be created based on response specific_currency_id = specific_currency_id.upper() self.__websockets['binance'][specific_currency_id] = websocket self.__websockets_callbacks['binance'][specific_currency_id] = callback diff --git a/Blankly/exchanges/managers/websocket_manager.py b/Blankly/exchanges/managers/websocket_manager.py index d3ceebbe..18db3f6b 100644 --- a/Blankly/exchanges/managers/websocket_manager.py +++ b/Blankly/exchanges/managers/websocket_manager.py @@ -16,10 +16,10 @@ along with this program. If not, see . """ import Blankly.utils.utils -from Blankly.exchanges.IExchange_Websocket import IExchangeWebsocket +from Blankly.exchanges.abc_exchange_websocket import ABCExchangeWebsocket -class WebsocketManager(IExchangeWebsocket): +class WebsocketManager(ABCExchangeWebsocket): def __init__(self, websockets, default_currency, default_exchange): self.websockets = websockets self.__default_currency = default_currency @@ -157,6 +157,6 @@ def get_most_recent_tick(self, override_currency=None, override_exchange=None): Get the most recent tick received """ websocket = self.__evaluate_overrides(override_currency, override_exchange) - # TODO fix the returned value below, really this needs a class like in Binance that can create a callback to + # TODO fix the returned value below, really this needs a class like in binance that can create a callback to # allow a pointer to be subbed in for whichever exchange/currency/websocket type is overridden return websocket.get_most_recent_tick() diff --git a/Blankly/exchanges/orders/limit_order.py b/Blankly/exchanges/orders/limit_order.py index 9d6aa097..272f2313 100644 --- a/Blankly/exchanges/orders/limit_order.py +++ b/Blankly/exchanges/orders/limit_order.py @@ -45,7 +45,7 @@ def __init__(self, order, response, interface): "settled": false } - Binance Response: + binance Response: { "symbol": "BTCUSDT", "orderId": 28, diff --git a/Blankly/exchanges/orders/market_order.py b/Blankly/exchanges/orders/market_order.py index 7cbc6b26..5eb422cb 100644 --- a/Blankly/exchanges/orders/market_order.py +++ b/Blankly/exchanges/orders/market_order.py @@ -44,7 +44,7 @@ def __init__(self, order, response, interface): 'settled': False } - Binance Response: + binance Response: TODO add this Guaranteed: diff --git a/Blankly/exchanges/orders/stop_limit.py b/Blankly/exchanges/orders/stop_limit.py index f96eed02..d11044d2 100644 --- a/Blankly/exchanges/orders/stop_limit.py +++ b/Blankly/exchanges/orders/stop_limit.py @@ -47,7 +47,7 @@ def __init__(self, order, response, interface): 'status': 'pending', 'settled': False } - Binance Response: + binance Response: TODO add this Guaranteed: diff --git a/Blankly/strategy/blankly_bot.py b/Blankly/strategy/blankly_bot.py index ec4bde6f..ec24582f 100644 --- a/Blankly/strategy/blankly_bot.py +++ b/Blankly/strategy/blankly_bot.py @@ -23,7 +23,7 @@ from Blankly.exchanges.managers.orderbook_manager import OrderbookManger from Blankly.exchanges.managers.ticker_manager import TickerManager -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface from Blankly.exchanges.interfaces.Coinbase_Pro.Coinbase_Pro_API import API as Coinbase_Pro_API from binance.client import Client as Binance_API @@ -36,7 +36,7 @@ class BlanklyBot: # Define the given types for the user Orderbook_Manager: OrderbookManger Ticker_Manager: TickerManager - Interface: ICurrencyInterface + Interface: ABCExchangeInterface coinbase_pro_direct: Coinbase_Pro_API binance_direct: Binance_API diff --git a/Blankly/strategy/cookbook/recipes.py b/Blankly/strategy/recipes/recipes.py similarity index 100% rename from Blankly/strategy/cookbook/recipes.py rename to Blankly/strategy/recipes/recipes.py diff --git a/Blankly/strategy/strategy_base.py b/Blankly/strategy/strategy_base.py index 7d4ea570..63069610 100644 --- a/Blankly/strategy/strategy_base.py +++ b/Blankly/strategy/strategy_base.py @@ -19,14 +19,14 @@ from Blankly.strategy.strategy_state import StrategyState from Blankly.utils.utils import AttributeDict -from Blankly.exchanges.interfaces.Paper_Trade.backtest_result import BacktestResult +from Blankly.exchanges.interfaces.paper_trade.backtest_result import BacktestResult import typing import time import pandas as pd import datetime import Blankly -from Blankly.exchanges.interfaces.Paper_Trade.backtest_controller import BackTestController +from Blankly.exchanges.interfaces.paper_trade.backtest_controller import BackTestController from Blankly.exchanges.exchange import Exchange from Blankly.utils.time_builder import time_interval_to_seconds diff --git a/Blankly/strategy/strategy_state.py b/Blankly/strategy/strategy_state.py index c1e36099..54a51b41 100644 --- a/Blankly/strategy/strategy_state.py +++ b/Blankly/strategy/strategy_state.py @@ -18,7 +18,7 @@ from Blankly.utils.utils import AttributeDict -from Blankly.exchanges.interfaces.abc_currency_interface import ICurrencyInterface as Interface +from Blankly.exchanges.interfaces.abc_exchange_interface import ABCExchangeInterface as Interface class StrategyState: diff --git a/Blankly/strategy/strategy_usage_example.py b/Blankly/strategy/strategy_usage_example.py index a31f0880..4aad537e 100644 --- a/Blankly/strategy/strategy_usage_example.py +++ b/Blankly/strategy/strategy_usage_example.py @@ -41,7 +41,7 @@ def rsi(price, ticker, interface: Blankly.Interface, state: StrategyState): if __name__ == "__main__": - coinbase_pro = Blankly.Coinbase_Pro() + coinbase_pro = Blankly.CoinbasePro() alpaca = Blankly.Alpaca() coinbase_strategy = Strategy(coinbase_pro) diff --git a/Blankly/utils/scheduler.py b/Blankly/utils/scheduler.py index 7f656918..db393c71 100644 --- a/Blankly/utils/scheduler.py +++ b/Blankly/utils/scheduler.py @@ -30,7 +30,7 @@ def __init__(self, function, interval, initially_stopped=False, **kwargs): Args: function: Function reference to create the scheduler on ex: self.price_event interval: int of delay between calls in seconds, or a string that takes units s, m, h, d w, M, y (second, - minute, hour, day, week, month, year) after a magnitude. Examples: "4s", "6h", "10d". + minute, hour, day, week, month, year) after a magnitude. examples: "4s", "6h", "10d". """ if isinstance(interval, str): interval = time_interval_to_seconds(interval) diff --git a/README.md b/README.md index 080f1331..403d44aa 100644 --- a/README.md +++ b/README.md @@ -76,52 +76,52 @@ import time def price_event(price: float, ticker: str, state: StrategyState): - interface = state.interface + interface = state.interface - # Add this most recent price to be stored for this particular price event - history = state.variables['history'] - history.append(price) + # Add this most recent price to be stored for this particular price event + history = state.variables['history'] + history.append(price) - # easily integrate your model - decision = my_awesome_model(history) + # easily integrate your model + decision = my_awesome_model(history) - # buy or sell based on that decision - if decision: - interface.market_order(ticker, 'buy', interface.cash) - state.variables['has_buy_order'] = True - elif state.variables['has_buy_order'] and not decision: - amt = interface.account[ticker].available - interface.market_order(ticker, 'sell', amt) - state.variables['has_buy_order'] = False + # buy or sell based on that decision + if decision: + interface.market_order(ticker, 'buy', interface.cash) + state.variables['has_buy_order'] = True + elif state.variables['has_buy_order'] and not decision: + amt = interface.account[ticker].available + interface.market_order(ticker, 'sell', amt) + state.variables['has_buy_order'] = False # Easily run setup code def strategy_init(currency_pair, state: StrategyState): - # get 500 points worth of data at given resolution of strategy - state.variables['history'] = - state.interface.history(currency_pair, 500, state.resolution)['close'] + # get 500 points worth of data at given resolution of strategy + state.variables['history'] = + state.interface.history(currency_pair, 500, state.resolution)['close'] if __name__ == "__main__": - # All authentication is done in this line - exchange = Blankly.Coinbase_Pro() + # All authentication is done in this line + exchange = Blankly.CoinbasePro() - # Now just wrap it into a strategy to gain a huge amount of functionality - strategy = Strategy(exchange) + # Now just wrap it into a strategy to gain a huge amount of functionality + strategy = Strategy(exchange) - # Run the code above with a new price once a day - strategy.add_price_event(price_event, - currency_pair='BTC-USD', - resolution='1h', - init=strategy_init) + # Run the code above with a new price once a day + strategy.add_price_event(price_event, + currency_pair='BTC-USD', + resolution='1h', + init=strategy_init) - # Run the code above with a new price once every thirty minutes - strategy.add_price_event(price_event, - currency_pair='LINK-USD', - resolution='30m', - init=strategy_init) + # Run the code above with a new price once every thirty minutes + strategy.add_price_event(price_event, + currency_pair='LINK-USD', + resolution='30m', + init=strategy_init) - strategy.start() + strategy.start() ``` diff --git a/Examples/README.md b/examples/README.md similarity index 80% rename from Examples/README.md rename to examples/README.md index bc6747d5..7b8af165 100644 --- a/Examples/README.md +++ b/examples/README.md @@ -1,4 +1,4 @@ ## Setting up is easy: 1. *Rename or create a new file of the format* `keys_example.json` as `keys.json`. ***This is done to keep it out of version control (putting keys in git history can be bad).*** 2. Add your exchange keys to the new (non-version controlled) `keys.json` file -3. Run `basic_example.py`. You can change exchanges by changing the line `Blankly.Coinbase_Pro()` to what you're using, such as `Blankly.Binance()` \ No newline at end of file +3. Run `basic_example.py`. You can change exchanges by changing the line `Blankly.CoinbasePro()` to what you're using, such as `Blankly.Binance()` \ No newline at end of file diff --git a/Examples/backtest.json b/examples/backtest.json similarity index 100% rename from Examples/backtest.json rename to examples/backtest.json diff --git a/Examples/backtesting_example.py b/examples/backtesting_example.py similarity index 96% rename from Examples/backtesting_example.py rename to examples/backtesting_example.py index 8036368c..41df1fe4 100644 --- a/Examples/backtesting_example.py +++ b/examples/backtesting_example.py @@ -22,7 +22,7 @@ def price_event(price, product_id, state): """ print("Authenticating...") # Create an authenticated coinbase pro object - coinbase_pro = Blankly.Coinbase_Pro() + coinbase_pro = Blankly.CoinbasePro() # Create a strategy object strategy = Blankly.Strategy(coinbase_pro) diff --git a/Examples/basic_example.py b/examples/basic_example.py similarity index 96% rename from Examples/basic_example.py rename to examples/basic_example.py index 605fb692..71e009f0 100644 --- a/Examples/basic_example.py +++ b/examples/basic_example.py @@ -10,7 +10,7 @@ def price_event(price, currency_pair, state): if __name__ == "__main__": # Authenticate coinbase pro strategy - coinbase_pro = Blankly.Coinbase_Pro() + coinbase_pro = Blankly.CoinbasePro() # Define our interface in case we want to make our own API calls interface = coinbase_pro.get_interface() diff --git a/Examples/keys_example.json b/examples/keys_example.json similarity index 100% rename from Examples/keys_example.json rename to examples/keys_example.json diff --git a/Examples/modeling_example.py b/examples/modeling_example.py similarity index 97% rename from Examples/modeling_example.py rename to examples/modeling_example.py index 8d02c6c2..dd068aed 100644 --- a/Examples/modeling_example.py +++ b/examples/modeling_example.py @@ -7,7 +7,7 @@ market = 'BTC-USD' p = figure(plot_width=800, plot_height=900) # Construct our authenticated exchange - portfolio = Blankly.Coinbase_Pro() + portfolio = Blankly.CoinbasePro() # Get the interface for API calls interface = portfolio.get_interface() diff --git a/Examples/multicore_bot.py b/examples/multicore_bot.py similarity index 97% rename from Examples/multicore_bot.py rename to examples/multicore_bot.py index dffb6515..1b174ac0 100644 --- a/Examples/multicore_bot.py +++ b/examples/multicore_bot.py @@ -48,7 +48,7 @@ def price_event(self, tick): # This creates an authenticated exchange and chooses the first portfolio in the keys.json file # You can use portfolio_name="my cool portfolio" if want a certain one - portfolio = Blankly.Coinbase_Pro() # You could also use Blankly.Binance() + portfolio = Blankly.CoinbasePro() # You could also use Blankly.binance() # Create the bot and add it to run as a coinbase_pro bitcoin model. bot = Bot() diff --git a/Examples/settings.json b/examples/settings.json similarity index 100% rename from Examples/settings.json rename to examples/settings.json diff --git a/tests/exchanges/interfaces/alpaca/alpaca_api_interface_test.py b/tests/exchanges/interfaces/alpaca/test_alpaca_interface.py similarity index 100% rename from tests/exchanges/interfaces/alpaca/alpaca_api_interface_test.py rename to tests/exchanges/interfaces/alpaca/test_alpaca_interface.py diff --git a/tests/exchanges/interfaces/alpaca/alpaca_interface_functional_test.py b/tests/exchanges/interfaces/alpaca/test_alpaca_interface_functional.py similarity index 100% rename from tests/exchanges/interfaces/alpaca/alpaca_interface_functional_test.py rename to tests/exchanges/interfaces/alpaca/test_alpaca_interface_functional.py diff --git a/tests/exchanges/interfaces/binance/test_binance_interface.py b/tests/exchanges/interfaces/binance/test_binance_interface.py index 7316b637..efa69352 100644 --- a/tests/exchanges/interfaces/binance/test_binance_interface.py +++ b/tests/exchanges/interfaces/binance/test_binance_interface.py @@ -1,5 +1,5 @@ """ - Unit tests for Binance. + Unit tests for binance. Copyright (C) 2021 Emerson Dove This program is free software: you can redistribute it and/or modify diff --git a/tests/exchanges/interfaces/coinbase_pro/test_coinbase_pro_interface.py b/tests/exchanges/interfaces/coinbase_pro/test_coinbase_pro_interface.py index 4b9e830a..574d34a1 100644 --- a/tests/exchanges/interfaces/coinbase_pro/test_coinbase_pro_interface.py +++ b/tests/exchanges/interfaces/coinbase_pro/test_coinbase_pro_interface.py @@ -29,9 +29,9 @@ class CoinbaseInterface2(unittest.TestCase): @classmethod def setUpClass(cls) -> None: - cls.Coinbase_Pro = Blankly.Coinbase_Pro(portfolio_name="Sandbox Portfolio", - keys_path='./tests/config/keys.json', - settings_path="./tests/config/settings.json") + cls.Coinbase_Pro = Blankly.CoinbasePro(portfolio_name="Sandbox Portfolio", + keys_path='./tests/config/keys.json', + settings_path="./tests/config/settings.json") cls.Coinbase_Pro_Interface = cls.Coinbase_Pro.get_interface() def test_get_exchange_type(self): diff --git a/tests/exchanges/test_interface_homogeneity.py b/tests/exchanges/test_interface_homogeneity.py index b9ff9e29..603b3af0 100644 --- a/tests/exchanges/test_interface_homogeneity.py +++ b/tests/exchanges/test_interface_homogeneity.py @@ -44,24 +44,24 @@ def setUpClass(cls) -> None: cls.Interfaces = [] # Coinbase Pro definition and appending - cls.Coinbase_Pro = Blankly.Coinbase_Pro(portfolio_name="Sandbox Portfolio", - keys_path='./tests/config/keys.json', - settings_path="./tests/config/settings.json") + cls.Coinbase_Pro = Blankly.CoinbasePro(portfolio_name="Sandbox Portfolio", + keys_path='./tests/config/keys.json', + settings_path="./tests/config/settings.json") cls.Coinbase_Pro_Interface = cls.Coinbase_Pro.get_interface() cls.Interfaces.append(cls.Coinbase_Pro_Interface) - # Binance definition and appending + # binance definition and appending cls.Binance = Blankly.Binance(portfolio_name="Spot Test Key", keys_path='./tests/config/keys.json', settings_path="./tests/config/settings.json") cls.Binance_Interface = cls.Binance.get_interface() cls.Interfaces.append(cls.Binance_Interface) - # Alpaca definition and appending - # cls.Alpaca = Blankly.Alpaca(portfolio_name="alpaca test portfolio", + # alpaca definition and appending + # cls.alpaca = Blankly.alpaca(portfolio_name="alpaca test portfolio", # keys_path='./tests/config/keys.json', # settings_path="./tests/config/settings.json") - # cls.Alpaca_Interface = cls.Alpaca.get_interface() + # cls.Alpaca_Interface = cls.alpaca.get_interface() # cls.Interfaces.append(cls.Alpaca_Interface) # Paper trade wraps binance