Skip to content

Commit

Permalink
fixes #27, working on #28
Browse files Browse the repository at this point in the history
  • Loading branch information
timkpaine committed Jun 10, 2019
1 parent e46b2b5 commit 5f649aa
Show file tree
Hide file tree
Showing 21 changed files with 893 additions and 212 deletions.
5 changes: 5 additions & 0 deletions aat/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ class ExchangeConfig(HasTraits):
instruments = List(trait=Instance(Instrument), default_value=[Instrument(type=InstrumentType.PAIR, underlying=PairType.BTCUSD)])


class SyntheticExchangeConfig(ExchangeConfig):
exchange_type = Instance(ExchangeType)
adversaries = List(default_value=[])


class BacktestConfig(HasTraits):
pass

Expand Down
137 changes: 137 additions & 0 deletions aat/exchanges/synthetic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import ccxt
import json
from datetime import datetime
from functools import lru_cache
from typing import List
from ..config import SyntheticExchangeConfig
from ..enums import ExchangeType, TickType, PairType, OrderType, CurrencyType
from ..exchange import Exchange
from ..order_book import OrderBook
from ..structs import MarketData, TradeRequest, TradeResponse, Instrument, Account


class SyntheticExchange(Exchange):
def __init__(self,
exchange_type: ExchangeType,
options: SyntheticExchangeConfig,
query_engine=None) -> None:
super(SyntheticExchange, self).__init__(exchange_type=exchange_type, options=options, query_engine=query_engine)
self._book = OrderBook(options.instruments)
self._underlying_exchange = options.exchange_type
self._advesaries = []

def generateMsg(self):
raise NotImplementedError()

async def receive(self) -> None:
async for msg in self.generateMsg():
self.callback_data(json.loads(msg.data))

@lru_cache(None)
def oe_client(self):
return ccxt.coinbasepro({'enableRateLimit': True})

async def close(self) -> None:
'''close the websocket'''
pass

@lru_cache(None)
def accounts(self):
all_curs = set()
for inst in self._options.instruments:
all_curs.add(inst.underlying.value[0])
all_curs.add(inst.underlying.value[1])

return [Account(id=str(cur.value),
currency=cur,
balance=100,
exchange=self.exchange(),
value=-1,
asOf=datetime.now()) for cur in all_curs]

@lru_cache(None)
def currencies(self) -> List[CurrencyType]:
return [CurrencyType(x) for x in self.oe_client().fetch_curencies()]

@lru_cache(None)
def markets(self) -> List[Instrument]:
return [Instrument(underlying=PairType.from_string(m['symbol'])) for m in self.oe_client().fetch_markets()]

def orderBook(self, level=1):
'''get order book'''
raise NotImplementedError()

def buy(self, req: TradeRequest) -> TradeResponse:
'''execute a buy order'''
for ad in self._advesaries:
req = ad.beforeOrder(req)

raise NotImplementedError()

for ad in self._advesaries:
req = ad.afterOrder(req)

def sell(self, req: TradeRequest) -> TradeResponse:
'''execute a sell order'''
for ad in self._advesaries:
req = ad.beforeOrder(req)

raise NotImplementedError()

for ad in self._advesaries:
req = ad.afterOrder(req)

def cancel(self, resp: TradeResponse):
for ad in self._advesaries:
resp = ad.beforeOrder(resp)

raise NotImplementedError()

for ad in self._advesaries:
resp = ad.afterOrder(resp)

def cancelAll(self, resp: TradeResponse):
pass

@lru_cache(None)
def subscription(self):
return []

@lru_cache(None)
def heartbeat(self):
return []

def tickToData(self, jsn: dict) -> MarketData:
pass

def strToTradeType(self, s: str, reason: str = '') -> TickType:
pass

def tradeReqToParams(self, req) -> dict:
pass

def currencyPairToString(self, cur: PairType) -> str:
pass

def orderTypeToString(self, typ: OrderType) -> str:
pass

def reasonToTradeType(self, s: str) -> TickType:
pass


class Adversary(object):
def __init__(self):
pass

def beforeData(self, data: MarketData, orig: MarketData) -> MarketData:
pass

def afterData(self, market) -> None:
pass

def beforeOrder(self, data: TradeRequest, market) -> None:
pass

def afterOrder(self, data: TradeResponse, market) -> None:
pass
1 change: 0 additions & 1 deletion aat/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@ def main(argv: list) -> None:
# exchange/backtest engine.

te = TradingEngine(config)

# Run the live trading engine
te.run()
6 changes: 3 additions & 3 deletions aat/order_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from functools import lru_cache
from typing import List
from .data_source import RestAPIDataSource
from .enums import PairType, TradingType, CurrencyType
from .enums import PairType, TradingType, CurrencyType, ExchangeType_to_string
from .exceptions import AATException
from .structs import TradeRequest, TradeResponse, Account, Instrument
from .utils import (get_keys_from_environment, str_to_currency_type,
Expand All @@ -17,9 +17,9 @@ class OrderEntry(RestAPIDataSource):
def oe_client(self):
options = self.options()
if options.trading_type == TradingType.SANDBOX:
key, secret, passphrase = get_keys_from_environment(self.exchange().value + '_SANDBOX')
key, secret, passphrase = get_keys_from_environment(ExchangeType_to_string(self.exchange()) + '_SANDBOX')
else:
key, secret, passphrase = get_keys_from_environment(self.exchange().value)
key, secret, passphrase = get_keys_from_environment(ExchangeType_to_string(self.exchange()))

return exchange_type_to_ccxt_client(self.exchange())({
'apiKey': key,
Expand Down
11 changes: 10 additions & 1 deletion aat/parser.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import os
import os.path
from configparser import ConfigParser
from pydoc import locate
from .config import TradingEngineConfig, BacktestConfig, StrategyConfig
from .enums import TradingType, InstrumentType
from .enums import TradingType, InstrumentType, ExchangeType
from .exceptions import ConfigException
from .structs import Instrument
from .utils import str_to_exchange, set_verbose, str_to_currency_pair_type
from .logging import LOG as log


def parse_file_config(filename: str) -> TradingEngineConfig:
if not os.path.exists(filename):
raise ConfigException(f'File does not exist {filename}')
config = TradingEngineConfig()
c = ConfigParser()
c.read(filename)
Expand Down Expand Up @@ -133,6 +137,11 @@ def _parse_currencies(currencies):
def _parse_options(argv, config: TradingEngineConfig) -> None:
if argv.get('exchanges'):
config.exchange_options.exchange_types = [str_to_exchange(x) for x in argv['exchanges'].split() if x]
for exchange in config.exchange_options.exchange_types:
if config.type == TradingType.LIVE and exchange == ExchangeType.SYNTHETIC:
raise ConfigException('Cannot run synthetic exchange in live mode!')
elif exchange == ExchangeType.SYNTHETIC:
config.exchange_options.exchange_type = ExchangeType.COINBASE
else:
raise ConfigException('No exchange set!')

Expand Down
17 changes: 17 additions & 0 deletions aat/tests/ui/handlers/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from .trading import TradingEngine
from .parser import parse_command_line_config


def generateApplication():
config = parse_command_line_config(['--config=./config/sythetic.cfg'])

# Instantiate trading engine
#
# The engine is responsible for managing the different components,
# including the strategies, the bank/risk engine, and the
# exchange/backtest engine.

te = TradingEngine(config)

# Run the live trading engine
te.run()
28 changes: 28 additions & 0 deletions aat/tests/ui/handlers/test_exchanges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tornado.web
import os.path
from ....ui.handlers.exchanges import ExchangesHandler
from mock import MagicMock


class TestAccounts:
def setup(self):
settings = {
"debug": "True",
"template_path": os.path.join(os.path.dirname(__file__), '../', '../', '../', 'ui', 'assets', 'templates'),
}

self.app = tornado.web.Application(**settings)
self.app._transforms = []

def test_AccountsHandler(self):
req = MagicMock()
req.body = ''
x = ExchangesHandler(self.app, req, trading_engine=MagicMock(), psp_kwargs={})

x.te.exchanges = MagicMock()
x.te.exchanges.return_value.values.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value[0].to_dict.return_value = {'test': 1}

x._transforms = []
x.get()
28 changes: 28 additions & 0 deletions aat/tests/ui/handlers/test_last_price.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tornado.web
import os.path
from ....ui.handlers.accounts import AccountsHandler
from mock import MagicMock


class TestAccounts:
def setup(self):
settings = {
"debug": "True",
"template_path": os.path.join(os.path.dirname(__file__), '../', '../', '../', 'ui', 'assets', 'templates'),
}

self.app = tornado.web.Application(**settings)
self.app._transforms = []

def test_AccountsHandler(self):
req = MagicMock()
req.body = ''
x = AccountsHandler(self.app, req, trading_engine=MagicMock(), psp_kwargs={})

x.te.exchanges = MagicMock()
x.te.exchanges.return_value.values.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value[0].to_dict.return_value = {'test': 1}

x._transforms = []
x.get()
28 changes: 28 additions & 0 deletions aat/tests/ui/handlers/test_strategies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tornado.web
import os.path
from ....ui.handlers.accounts import AccountsHandler
from mock import MagicMock


class TestAccounts:
def setup(self):
settings = {
"debug": "True",
"template_path": os.path.join(os.path.dirname(__file__), '../', '../', '../', 'ui', 'assets', 'templates'),
}

self.app = tornado.web.Application(**settings)
self.app._transforms = []

def test_AccountsHandler(self):
req = MagicMock()
req.body = ''
x = AccountsHandler(self.app, req, trading_engine=MagicMock(), psp_kwargs={})

x.te.exchanges = MagicMock()
x.te.exchanges.return_value.values.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value[0].to_dict.return_value = {'test': 1}

x._transforms = []
x.get()
28 changes: 28 additions & 0 deletions aat/tests/ui/handlers/test_strategy_trade_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tornado.web
import os.path
from ....ui.handlers.accounts import AccountsHandler
from mock import MagicMock


class TestAccounts:
def setup(self):
settings = {
"debug": "True",
"template_path": os.path.join(os.path.dirname(__file__), '../', '../', '../', 'ui', 'assets', 'templates'),
}

self.app = tornado.web.Application(**settings)
self.app._transforms = []

def test_AccountsHandler(self):
req = MagicMock()
req.body = ''
x = AccountsHandler(self.app, req, trading_engine=MagicMock(), psp_kwargs={})

x.te.exchanges = MagicMock()
x.te.exchanges.return_value.values.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value[0].to_dict.return_value = {'test': 1}

x._transforms = []
x.get()
28 changes: 28 additions & 0 deletions aat/tests/ui/handlers/test_strategy_trade_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import tornado.web
import os.path
from ....ui.handlers.accounts import AccountsHandler
from mock import MagicMock


class TestAccounts:
def setup(self):
settings = {
"debug": "True",
"template_path": os.path.join(os.path.dirname(__file__), '../', '../', '../', 'ui', 'assets', 'templates'),
}

self.app = tornado.web.Application(**settings)
self.app._transforms = []

def test_AccountsHandler(self):
req = MagicMock()
req.body = ''
x = AccountsHandler(self.app, req, trading_engine=MagicMock(), psp_kwargs={})

x.te.exchanges = MagicMock()
x.te.exchanges.return_value.values.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value = [MagicMock()]
x.te.exchanges.return_value.values.return_value[0].accounts.return_value[0].to_dict.return_value = {'test': 1}

x._transforms = []
x.get()

0 comments on commit 5f649aa

Please sign in to comment.