Skip to content

Commit

Permalink
Merge pull request #106 from AsyncAlgoTrading/pm
Browse files Browse the repository at this point in the history
Portfolio loading
  • Loading branch information
timkpaine committed Sep 28, 2020
2 parents f75f090 + d0ebf73 commit 95e38f5
Show file tree
Hide file tree
Showing 38 changed files with 346 additions and 76 deletions.
3 changes: 2 additions & 1 deletion aat/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .config import * # noqa: F401, F403
from .core import EventHandler, Instrument, ExchangeType, Data, Event, Order, Position, Trade, OrderBook, TradingEngine # noqa: F401
from .core import EventHandler, Instrument, ExchangeType, Data, Event, Order, Position, Trade, OrderBook # noqa: F401
from .engine import TradingEngine # noqa: F401
from .strategy import * # noqa: F401, F403
2 changes: 1 addition & 1 deletion aat/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .config import parseConfig
from .core import TradingEngine
from .engine import TradingEngine


def main() -> None:
Expand Down
11 changes: 9 additions & 2 deletions aat/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
from .parser import parseConfig, getStrategies, getExchanges # noqa: F401

if _in_cpp():
from ..binding import TradingTypeCpp as TradingType, SideCpp as Side, InstrumentTypeCpp as InstrumentType, EventTypeCpp as EventType, DataTypeCpp as DataType, OrderTypeCpp as OrderType, OrderFlagCpp as OrderFlag # type: ignore # noqa: F401
from ..binding import (TradingTypeCpp as TradingType, # type: ignore
SideCpp as Side,
InstrumentTypeCpp as InstrumentType,
EventTypeCpp as EventType,
DataTypeCpp as DataType,
OrderTypeCpp as OrderType,
OrderFlagCpp as OrderFlag,
ExitRoutineCpp as ExitRoutine) # noqa: F401
else:
from .enums import TradingType, Side, InstrumentType, EventType, DataType, OrderFlag, OrderType # noqa: F401
from .enums import TradingType, Side, InstrumentType, EventType, DataType, OrderFlag, OrderType, OptionType, ExitRoutine # noqa: F401
5 changes: 5 additions & 0 deletions aat/config/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@ class OrderFlag(BaseEnum):
FILL_OR_KILL = 'FILL_OR_KILL'
ALL_OR_NONE = 'ALL_OR_NONE'
IMMEDIATE_OR_CANCEL = 'IMMEDIATE_OR_CANCEL'


class ExitRoutine(BaseEnum):
NONE = 'NONE'
CLOSE_ALL = 'CLOSE_ALL'
14 changes: 14 additions & 0 deletions aat/config/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ def _args_to_dict(args):
ret['general'] = {}
ret['general']['verbose'] = args.verbose
ret['general']['trading_type'] = args.trading_type
ret['general']['load_accounts'] = args.load_accounts
ret['general']['api'] = args.api
ret['exchange'] = {'exchanges': list(_.split(',') for _ in itertools.chain.from_iterable(args.exchanges))}
ret['strategy'] = {'strategies': list(itertools.chain.from_iterable(args.strategies))}
return ret
Expand Down Expand Up @@ -95,6 +97,18 @@ def parseConfig(argv: list = None) -> dict:
help='Run in verbose mode',
default=False)

parser.add_argument(
'--api',
action='store_true',
help='Enable HTTP server',
default=False)

parser.add_argument(
'--load_accounts',
action='store_true',
help='Load accounts from exchanges',
default=False)

parser.add_argument(
'--trading_type',
help='Trading Type in ("live", "sandbox", "simulation", "backtest")',
Expand Down
3 changes: 0 additions & 3 deletions aat/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,3 @@
from ..binding import InstrumentCpp, DataCpp, EventCpp, OrderCpp, TradeCpp, OrderBookCpp # type: ignore # noqa: F401
except ImportError:
pass

# import last
from .engine import TradingEngine, StrategyManager # noqa: F401
2 changes: 0 additions & 2 deletions aat/core/engine/__init__.py

This file was deleted.

2 changes: 0 additions & 2 deletions aat/core/engine/manager/__init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion aat/core/handler/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

if TYPE_CHECKING:
# Circular import
from ..engine import StrategyManager
from aat.engine import StrategyManager


class EventHandler(metaclass=ABCMeta):
Expand Down
1 change: 0 additions & 1 deletion aat/core/risk/__init__.py

This file was deleted.

16 changes: 16 additions & 0 deletions aat/cpp/include/aat/config/enums.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ namespace config {
IMMEDIATE_OR_CANCEL = 3,
};

enum class ExitRoutine {
NONE = 0,
CLOSE_ALL = 1,
};

static const std::vector<str_t> TradingType_names = {
"LIVE",
"SIMULATION",
Expand Down Expand Up @@ -168,6 +173,11 @@ namespace config {
"IMMEDIATE_OR_CANCEL",
};

static const std::vector<str_t> ExitRoutine_names = {
"NONE",
"CLOSE_ALL",
};

static std::unordered_map<str_t, TradingType> _TradingType_mapping = {
{"LIVE", TradingType::LIVE},
{"SIMULATION", TradingType::SIMULATION},
Expand Down Expand Up @@ -240,6 +250,11 @@ namespace config {
{"IMMEDIATE_OR_CANCEL", OrderFlag::IMMEDIATE_OR_CANCEL},
};

static std::unordered_map<str_t, ExitRoutine> _ExitRoutine_mapping = {
{"NONE", ExitRoutine::NONE},
{"CLOSE_ALL", ExitRoutine::CLOSE_ALL},
};

ENUM_TO_STRING(TradingType)
ENUM_TO_STRING(Side)
ENUM_TO_STRING(OptionType)
Expand All @@ -255,5 +270,6 @@ namespace config {
ENUM_FROM_STRING(InstrumentType)
ENUM_FROM_STRING(OrderType)
ENUM_FROM_STRING(OrderFlag)
ENUM_FROM_STRING(ExitRoutine)
} // namespace config
} // namespace aat
5 changes: 5 additions & 0 deletions aat/cpp/include/aat/python/binding.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ PYBIND11_MODULE(binding, m) {
.value("IMMEDIATE_OR_CANCEL", OrderFlag::IMMEDIATE_OR_CANCEL)
.export_values();

py::enum_<ExitRoutine>(m, "ExitRoutineCpp", py::arithmetic())
.value("NONE", ExitRoutine::NONE)
.value("CLOSE_ALL", ExitRoutine::CLOSE_ALL)
.export_values();

/*******************************
* OrderBook
******************************/
Expand Down
2 changes: 2 additions & 0 deletions aat/engine/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .engine import TradingEngine # noqa: F401
from .dispatch import StrategyManager # noqa: F401
4 changes: 4 additions & 0 deletions aat/engine/dispatch/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .manager import StrategyManager # noqa: F401
from .execution import OrderManager # noqa: F401
from .portfolio import PortfolioManager, Portfolio # noqa: F401
from .risk import RiskManager # noqa: F401
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from aat.core import Order, Event
from aat.core.handler import EventHandler
from aat.core.engine.manager import ManagerBase
from aat.exchange import Exchange
from ..base import ManagerBase


class OrderManager(ManagerBase):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
import sys
import traceback

from typing import List
from typing import List, TYPE_CHECKING

from .order_entry import StrategyManagerOrderEntryMixin
from .portfolio import StrategyManagerPortfolioMixin
from .risk import StrategyManagerRiskMixin
from .utils import StrategyManagerUtilsMixin

from aat.config import TradingType
from aat.core.handler import EventHandler
from aat.exchange import Exchange

if TYPE_CHECKING:
from aat.engine import TradingEngine


class StrategyManager(StrategyManagerOrderEntryMixin, StrategyManagerRiskMixin, StrategyManagerPortfolioMixin, StrategyManagerUtilsMixin, EventHandler):
def __init__(self, trading_engine, trading_type, exchanges: List[Exchange]):
'''The Manager sits between the strategies and the engine and manages state'''
def __init__(self,
trading_engine: 'TradingEngine',
trading_type: TradingType,
exchanges: List[Exchange],
load_accounts: bool = False):
'''The Manager sits between the strategies and the engine and manages state
Args:
trading_engine (TradingEngine); the trading engine instance
trading_type (TradingType); the trading type
exchanges (List[Exchange]); a list of exchanges to dispatch to
load_accounts (bool); load positions from accounts on startup
'''

# store trading engine
self._engine = trading_engine

# store the exchanges
self._exchanges = exchanges

# store whether to query accounts on start
self._load_accounts = load_accounts

# pull from trading engine class
self._portfolio_mgr = self._engine.portfolio_manager
self._risk_mgr = self._engine.risk_manager
Expand Down Expand Up @@ -61,6 +80,12 @@ def orderManager(self):
def portfolioManager(self):
return self._portfolio_mgr

def strategies(self):
return self._engine.strategies

def exchanges(self):
return self._engine.exchanges

# ********************* #
# EventHandler methods *
# **********************
Expand Down Expand Up @@ -100,25 +125,35 @@ async def onContinue(self, event):
await self._order_mgr.onContinue(event)

async def onData(self, event):
# TODO
await self._portfolio_mgr.onData(event)
await self._risk_mgr.onData(event)
await self._order_mgr.onData(event)

async def onError(self, event):
# TODO
print('\n\nA Fatal Error has occurred:')
traceback.print_exception(type(event.target.exception), event.target.exception, event.target.exception.__traceback__)
sys.exit(1)

async def onExit(self, event):
# TODO
await self._portfolio_mgr.onExit(event)
await self._risk_mgr.onExit(event)
await self._order_mgr.onExit(event)

async def onStart(self, event):
# TODO
# Initialize strategies
self._portfolio_mgr.updateStrategies(self.strategies())

# Initialize positions
for exchange in self.exchanges():
if self._load_accounts:
acc = await exchange.accounts()
self._portfolio_mgr.updateAccount(acc)

acc = await exchange.balance()
self._portfolio_mgr.updateCash(acc)
self._risk_mgr.updateCash(acc)

# Defer to sub onStarts
await self._portfolio_mgr.onStart(event)
await self._risk_mgr.onStart(event)
await self._order_mgr.onStart(event)
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from typing import List, TYPE_CHECKING

from aat.core import Instrument, ExchangeType, Event, Order, Trade
from aat.core.execution import OrderManager
from aat.core.portfolio import PortfolioManager
from aat.core.risk import RiskManager
from aat.config import Side
from aat.exchange import Exchange

from .execution import OrderManager
from .portfolio import PortfolioManager
from .risk import RiskManager

if TYPE_CHECKING:
from aat.core import TradingEngine
from aat.engine import TradingEngine


class StrategyManagerOrderEntryMixin(object):
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .manager import PortfolioManager # noqa: F401
from .mixin import StrategyManagerPortfolioMixin # noqa: F401
from .portfolio import Portfolio # noqa: F401
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pandas as pd # type: ignore
from typing import Optional
from typing import Optional, List

from aat.core import Event, Trade, Instrument, ExchangeType
from aat.core import Event, Trade, Instrument, ExchangeType, Position
from aat.core.handler import EventHandler
from aat.core.engine.manager import ManagerBase

from ..base import ManagerBase
from .portfolio import Portfolio


Expand All @@ -27,16 +27,30 @@ def _setManager(self, manager):
self._manager = manager

def newPosition(self, strategy, trade: Trade):
'''create and track a new position, or update the pnl/price of
an existing position'''
self._portfolio.newPosition(strategy, trade)

def updateStrategies(self, strategies: List) -> None:
'''update with list of strategies'''
self._portfolio.updateStrategies(strategies)

def updateAccount(self, positions: List[Position]) -> None:
'''update positions tracking with a position from the exchange'''
self._portfolio.updateAccount(positions)

def updateCash(self, positions: List[Position]) -> None:
'''update cash positions from exchange'''
self._portfolio.updateCash(positions)

# *********************
# Risk Methods *
# *********************
def portfolio(self):
return self._portfolio

def positions(self, instrument: Instrument = None, exchange: ExchangeType = None):
return self._portfolio.positions(instrument=instrument, exchange=exchange)
def positions(self, strategy, instrument: Instrument = None, exchange: ExchangeType = None):
return self._portfolio.positions(strategy=strategy, instrument=instrument, exchange=exchange)

def priceHistory(self, instrument: Instrument = None):
if instrument:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class StrategyManagerPortfolioMixin(object):
def portfolio(self):
return self._portfolio_mgr.portfolio()

def positions(self, instrument=None, exchange=None):
return self._portfolio_mgr.positions(instrument=instrument, exchange=exchange)
def positions(self, strategy, instrument=None, exchange=None):
return self._portfolio_mgr.positions(strategy=strategy, instrument=instrument, exchange=exchange)

def priceHistory(self, instrument=None):
return self._portfolio_mgr.priceHistory(instrument=instrument)

0 comments on commit 95e38f5

Please sign in to comment.