class BacktestBroker(Broker): def __init__(self, hub: Hub) -> None: self.hub = hub self.publisher = Publisher(hub, prefix='broker') self.subscriber = Subscriber(hub, 'broker') self.subscriber.add_sync_listener(events.AnyNewTrade, self.log_trade_timestamp) self.orders = [] self.positions = [] self._timestamp = None def submit_order(self, order: Order) -> None: order.timestamp = self.get_timestamp() exchange = order.exchange self.publisher.publish([exchange.name, 'new-order'], order) self.orders.append(order) position = self.make_position(order) self.positions.append(position) position.open(order.price) def make_position(self, order: Order) -> Position: position = Position(order.market.quote, order.amount, timestamp=order.timestamp) self.publisher.publish([str(order.market), 'new-position'], position) return position def get_timestamp(self) -> datetime: if self._timestamp is not None: return self._timestamp else: return utc_now() def log_trade_timestamp(self, key: Key, trade: Trade) -> None: self._timestamp = trade.timestamp
def __init__(self, hub: Hub, filename: str) -> None: self.filename = filename logger.info("Reading csv") self.df = pd.read_csv(self.filename, names=COLUMN_NAMES) self.df.time = pd.to_datetime(self.df.time, unit='s') self.publisher = Publisher(hub, prefix='csv_trade_processor') logger.info("Reading done")
class ThresholdBarGenerator: """ ThresholdBarGenerator samples price statistics and generates a new bar when predefined threshold of given statistics has been reached. """ def __init__(self, hub: Hub, threshold: int): self.subscriber = Subscriber(hub, 'threshold_bars') self.subscriber.add_sync_listener(events.AnyNewTrade, self.on_new_trade) self.publisher = Publisher(hub, prefix='threshold_bars') self.threshold = threshold self.bar = None self.value = 0 def on_new_trade(self, key: Key, trade: Trade) -> None: if not self.bar: self.bar = Bar(trade) self.bar.append(trade) if self.value >= self.threshold: namespace = key[1] self._build_new_bar(trade, namespace) self.value += self.metric(trade) def _build_new_bar(self, trade: Trade, namespace: str) -> Bar: self.value = 0 key = [namespace, 'new-bar'] self.publisher.publish(key, self.bar) self.bar = Bar(trade) return self.bar
def __init__(self, hub: Hub, threshold: int): self.subscriber = Subscriber(hub, 'threshold_bars') self.subscriber.add_sync_listener(events.AnyNewTrade, self.on_new_trade) self.publisher = Publisher(hub, prefix='threshold_bars') self.threshold = threshold self.bar = None self.value = 0
def __init__(self, hub: Hub) -> None: self.hub = hub self.publisher = Publisher(hub, prefix='broker') self.subscriber = Subscriber(hub, 'broker') self.subscriber.add_sync_listener(events.AnyNewTrade, self.log_trade_timestamp) self.orders = [] self.positions = [] self._timestamp = None
def __init__(self, hub: Hub, exchange: Exchange, market: Market, date_range: Optional[DateRange] = None ) -> None: self.library_name = str(exchange) self.symbol = str(market) self.store = Arctic('localhost') self.library = self.store[self.library_name] self.date_range = date_range self.publisher = Publisher(hub, prefix='arctic_trade_processor')
def test_mullti_strategy_on_new_bar_is_called(): hub = Hub() publisher = Publisher(hub, 'test-publisher') trade = Trade(12345, price=1.0, amount=1.0) bar = Bar(trade) exchange = 'test' market = Markets.BTCEUR broker = BacktestBroker(hub) strat = NewBarTestMultiStrategy(hub, broker) publisher.publish([f'{exchange}-{market}', 'new-bar'], bar) assert strat.on_new_bar_called
def test_multi_strategy_stores_bars(): hub = Hub() publisher = Publisher(hub, 'test-publisher') bars = [1, 2, 3] exchange = 'test' market = Markets.BTCUSD broker = BacktestBroker(hub) strat = NewBarTestMultiStrategy(hub, broker) [ publisher.publish([f'{exchange}-{market}', 'new-bar'], bar) for bar in bars ] assert strat.bars['test-BTCUSD'] == bars
def test_tick_bar_generation_after_threshold(): hub = Hub() publisher = Publisher(hub, 'test-publisher') generator = TickBarGenerator(hub, threshold=3) subscriber = Subscriber(hub, 'test-subscriber') bars = [] def new_bar_handler(key, bar): bars.append(bar) subscriber.add_sync_listener(events.AnyNewBar, new_bar_handler) assert len(bars) == 0 for i in range(5): trade = Trade(12345, price=1.0, amount=1.0) publisher.publish(['test-BTCUSD', 'new-trade'], trade) assert len(bars) == 1
class CSVTradeProcessor: def __init__(self, hub: Hub, filename: str) -> None: self.filename = filename logger.info("Reading csv") self.df = pd.read_csv(self.filename, names=COLUMN_NAMES) self.df.time = pd.to_datetime(self.df.time, unit='s') self.publisher = Publisher(hub, prefix='csv_trade_processor') logger.info("Reading done") def run(self) -> None: logger.info("Processing trades from CSV") self.df.apply(self.send_signal, axis=1) logger.info("Finished, sending signal") self.publisher.publish(events.ProcessingFinished, None) def send_signal(self, row) -> None: trade = Trade(timestamp=row.time, price=row.price, amount=row.amount) self.publisher.publish(['csvfile-BTCUSD', 'new-trade'], trade)
class FeedProcessor: def __init__(self, hub: Hub, exchange_class: str, pair: str) -> None: self.feed = FeedHandler() self.publisher = Publisher(hub, prefix='feed_processor') self.pair = pair self._add_feed(exchange_class) def _add_feed(self, exchange_class: str): trades_feed = exchange_class(pairs=[self.pair], channels=[TRADES], callbacks={TRADES: TradeCallback(self.trade)}) self.feed.add_feed(trades_feed) def run(self) -> None: self.feed.run() async def trade(self, feed, pair, order_id, timestamp, side, amount, price): # print(f"Timestamp: {timestamp} Feed: {feed} Pair: {pair} ID: {order_id} Side: {side} Amount: {amount} Price: {price}") trade = Trade(timestamp=timestamp, price=price, amount=amount) self.publisher.publish([self.pair, 'new-trade'], trade)
def __init__(self, hub: Hub, initial_theta: int = 50) -> None: self.subscriber = Subscriber(hub, 'tick_imbalance_bar_generator') self.subscriber.add_sync_listener(events.AnyNewTrade, self.on_new_trade) self.publisher = Publisher(hub, prefix='tick_imbalance_bar_generator') self.bar = None self.last_trade = None self.b_ts = [] self.t_vals = [] self.theta = 0 self.expected_theta = initial_theta self.initial_T = 50
class ArcticTradeProcessor: def __init__(self, hub: Hub, exchange: Exchange, market: Market, date_range: Optional[DateRange] = None ) -> None: self.library_name = str(exchange) self.symbol = str(market) self.store = Arctic('localhost') self.library = self.store[self.library_name] self.date_range = date_range self.publisher = Publisher(hub, prefix='arctic_trade_processor') def run(self) -> None: logger.info("Processing trades from Arctic") item = self.library.read(self.symbol, date_range=self.date_range) logger.info("Finished reading, launching trades") item.data.apply(self.send_signal, axis=1) self.publisher.publish(events.ProcessingFinished, None) def send_signal(self, row) -> None: trade = Trade(timestamp=row.time, price=row.price, amount=row.amount) self.publisher.publish([f"{self.library_name}-{self.symbol}", 'new-trade'], trade)
def publisher(hub) -> Publisher: return Publisher(hub, 'test_publisher')
def publisher(hub): return Publisher(hub, 'test-publisher')
def __init__(self, hub: Hub, exchange_class: str, pair: str) -> None: self.feed = FeedHandler() self.publisher = Publisher(hub, prefix='feed_processor') self.pair = pair self._add_feed(exchange_class)