Skip to content

Commit

Permalink
alpaca interface integration
Browse files Browse the repository at this point in the history
  • Loading branch information
arun-annamalai committed May 27, 2021
1 parent 8072724 commit 6425272
Show file tree
Hide file tree
Showing 20 changed files with 407 additions and 19 deletions.
Empty file added Blankly/auth/Alpaca/__init__.py
Empty file.
26 changes: 26 additions & 0 deletions Blankly/auth/Alpaca/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from Blankly.auth.abc_auth import auth_interface

import warnings
class alpaca_auth(auth_interface):
def __init__(self, keys_file, portfolio_name):
super().__init__(keys_file, portfolio_name, 'alpaca')
self.API_KEY = None
self.API_SECRET = None
self.validate_credentials()

def validate_credentials(self):
"""
Validate that exchange specific credentials are present
"""
try:
self.API_KEY = self.raw_cred.pop('API_KEY')
self.API_SECRET = self.raw_cred.pop('API_SECRET')
except KeyError as e:
print(f"One of 'API_KEY' or 'API_SECRET' not defined for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name}")
raise KeyError(e)

if len(self.raw_cred) > 0:
warnings.warn("Additional configs for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name} being ignored")



Empty file.
26 changes: 26 additions & 0 deletions Blankly/auth/Binance/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from Blankly.auth.abc_auth import auth_interface
import warnings

class binance_auth(auth_interface):
def __init__(self, keys_file, portfolio_name):
super.__init__(keys_file, portfolio_name, 'binance')
self.API_KEY = None
self.API_SECRET = None
self.validate_credentials()

def validate_credentials(self):
"""
Validate that exchange specific credentials are present
"""
try:
self.API_KEY = self.raw_cred.pop('API_KEY')
self.API_SECRET = self.raw_cred.pop('API_SECRET')
except KeyError as e:
print(f"One of 'API_KEY' or 'API_SECRET' not defined for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name}")
raise KeyError(e)

if len(self.raw_cred) > 0:
warnings.warn(f"Additional configs for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name} being ignored")



Empty file.
29 changes: 29 additions & 0 deletions Blankly/auth/Coinbase/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from Blankly.auth.abc_auth import auth_interface
import warnings

class coinbase_auth(auth_interface):
def __init__(self, keys_file, portfolio_name):
super.__init__(keys_file, portfolio_name, 'coinbase')
self.API_KEY = None
self.API_SECRET = None
self.API_PASS = None

self.validate_credentials()

def validate_credentials(self):
"""
Validate that exchange specific credentials are present
"""
try:
self.API_KEY = self.raw_cred.pop('API_KEY')
self.API_SECRET = self.raw_cred.pop('API_SECRET')
self.API_PASS = self.raw_cred.pop('API_PASS')
except KeyError as e:
print(f"One of 'API_KEY' or 'API_SECRET' or 'API_PASS' not defined for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name}")
raise KeyError(e)

if len(self.raw_cred) > 0:
warnings.warn(f"Additional configs for Exchange: {self.__exchange} Portfolio: {self.__portfolio_name} being ignored")



Empty file added Blankly/auth/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions Blankly/auth/abc_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
Logic to provide consistency across exchanges
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 <https://www.gnu.org/licenses/>.
"""

import abc
from Blankly.auth.utils import load_json

class auth_interface(abc.ABC):
def __init__(self, keys_file, portfolio_name, exchange):
"""
Create a currency interface
Args:
keys_file (str): filepath to keys.json
portfolio_name (str): name of portfolio
"""
assert keys_file
assert portfolio_name
assert exchange
self.portfolio_name = portfolio_name
self.exchange = exchange
self.raw_cred = self.load_credentials(keys_file, portfolio_name, exchange)

def load_credentials(self, keys_file, portfolio_name, exchange):
"""
Load credentials from keys json file
"""
auth_object = load_json(keys_file)
exchange_keys = auth_object[exchange]
credentials = exchange_keys[portfolio_name]

return credentials

@abc.abstractmethod
def validate_credentials(self):
"""
Validate that exchange specific credentials are present
"""
pass
Empty file added Blankly/auth/auth.py
Empty file.
16 changes: 16 additions & 0 deletions Blankly/auth/auth_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from Blankly.auth.Alpaca.auth import alpaca_auth
from Blankly.auth.Binance.auth import binance_auth
from Blankly.auth.Coinbase.auth import coinbase_auth


class AuthFactory:
@staticmethod
def create_auth(self, keys_file, exchange_name, portfolio_name):
if exchange_name == 'alpaca':
return alpaca_auth(keys_file, portfolio_name)
elif exchange_name == 'binance':
return binance_auth(keys_file, portfolio_name)
elif exchange_name == 'coinbase_pro':
return coinbase_auth(keys_file, portfolio_name)
else:
raise KeyError("Exchange not supported")
22 changes: 22 additions & 0 deletions Blankly/auth/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import json
import warnings

def load_json(keys_file):
try:
f = open(keys_file)
return json.load(f)
except FileNotFoundError:
raise FileNotFoundError("Make sure a Keys.json file is placed in the same folder as the project working "
"directory!")

def default_first_portfolio(keys_file, exchange_name):
auth_object = load_json(keys_file)
exchange_keys = auth_object[exchange_name]
first_key = list(exchange_keys.keys())[0]
warning_string = "No portfolio name to load specified, defaulting to the first in the file: " \
"(" + first_key + "). This is fine if there is only one portfolio in use."
warnings.warn(warning_string)
# Read the first in the portfolio
portfolio = exchange_keys[first_key]
name = first_key
return name, portfolio
32 changes: 32 additions & 0 deletions Blankly/exchanges/Alpaca/Alpaca.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Coinbase Pro exchange definitions and setup
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 <https://www.gnu.org/licenses/>.
"""

from Blankly.exchanges.exchange import Exchange
from Blankly.auth.auth_factory import AuthFactory
from Blankly.auth.utils import default_first_portfolio
from Blankly.interface.currency_factory import InterfaceFactory

class Alpaca(Exchange):
def __init__(self, portfolio_name=None, auth_path="Keys.json", preferences_path=None):
if not portfolio_name:
portfolio_name = default_first_portfolio(auth_path, 'alpaca')
Exchange.__init__(self, 'alpaca', portfolio_name, preferences_path)
alpaca_auth = AuthFactory(auth_path, 'alpaca', portfolio_name)
self.interface = InterfaceFactory('alpaca', alpaca_auth, self.preferences)


10 changes: 6 additions & 4 deletions Blankly/exchanges/Alpaca/Alpaca_API.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from Blankly.auth.Alpaca.auth import alpaca_auth

import alpaca_trade_api as tradeapi
import os

Expand All @@ -6,18 +8,18 @@


class API:
def __init__(self, API_KEY, API_SECRET, paper_trading = False):
if (paper_trading):
def __init__(self, auth: alpaca_auth, paper_trading=True):
if paper_trading:
self.__api_url = APCA_API_PAPER_URL
else:
self.__api_url = APCA_API_LIVE_URL

self.alp_client = tradeapi.REST(API_KEY, API_SECRET, self.__api_url, 'v2')
self.alp_client = tradeapi.REST(auth.API_KEY, auth.API_SECRET, self.__api_url, 'v2')


api = os.getenv("ALPACA_PUBLIC")
secret = os.getenv("ALPACA_PRIVATE")

if __name__ == "__main__":
client = API(api, secret, True)
print(client.alp_client.list_assets())
print(client.alp_client.list_assets())
Loading

0 comments on commit 6425272

Please sign in to comment.