async def on_signal(self, action, update): strp_time = update['timestamp'].split('.')[0].split('+')[0] curr_time = time.mktime( dt.datetime.strptime(strp_time, '%Y-%m-%d %H:%M:%S').timetuple()) book = update['book'] if action == 'BUY': if self._pnl_manager.get_cash_value() <= Decimal(1.00): return price = make_price(book['asks'][0]['price']) cash = self._pnl_manager.get_cash_value() qty = cash / price await self._trader.submit_order(side=Side.BID, price=price, qty=make_qty(Decimal(qty)), ioc=True, quote=True) self._last_buy_ts = curr_time else: if self._pnl_manager.get_crypto_value(book) <= Decimal(0.01): return price = make_price(book['bids'][0]['price']) qty = self._pnl_manager.crypto_coins await self._trader.submit_order(side=Side.ASK, price=price, qty=make_qty(Decimal(qty)), ioc=True, quote=True) self._last_sell_ts = curr_time
async def persistent_submit(self, side, price, qty, ioc, quote): tries = 0 unsuccessful_submit = True p = price q = qty while (tries < 5 and unsuccessful_submit): try: await self._trader.submit_order(side=side, price=p, qty=q, ioc=ioc, quote=quote) unsuccessful_submit = False except PostOnlyException: previous_price = p previous_qty = q if side == Side.BID: p = previous_price - make_price(0.01) q = make_qty( Decimal(round((previous_qty * previous_price) / p, 8))) else: p = previous_price + make_price(0.01) q = make_qty( Decimal(round((previous_qty * previous_price) / p, 8))) tries += 1 if unsuccessful_submit: log.warning('Tried to place order 5x. Giving up...')
def main(args): params = { 'api_url': gdax.OrderEntryGateway.SANDBOX_URL, 'api_key': args['<API_KEY>'], 'api_secret': args['<API_SECRET>'], 'passphrase': args['<PASSPHRASE>'], 'ip': args['<IP>'], 'port': args['<PORT>'], 'sandbox': False if (args['<SANDBOX>'] == "False") else True, 'instrument': args['<INSTRUMENT>'] } log.info('Starting Anchor Strategy for {} in {} mode', params['instrument'], 'SANDBOX' if params['sandbox'] else 'PRODUCTION') # TODO: Set up limits through configuration StrategyConfig['limits'] = {} StrategyConfig['limits']['max_order_qty'] = make_qty('2') StrategyConfig['limits']['max_order_value'] = make_price('1000') StrategyConfig['limits']['max_open_value'] = 1000 loop = asyncio.get_event_loop() anchor_strategy = Anchor(loop) loop.run_until_complete(anchor_strategy.run(params))
async def socket_handler(self, request): resp = aiohttp.web.WebSocketResponse() ok, protocol = resp.can_prepare(request) if not ok: return aiohttp.web.Response(text='Somthing went wrong') await resp.prepare(request) try: request.app['sockets'].append(resp) async for msg in resp: if msg.type == aiohttp.web.WSMsgType.TEXT: req = json.loads(msg.data) if 'submit' in req: logging.info('Recieved request: {}'.format(req)) if is_valid_submit(req['submit']): submit = req['submit'] side = Side.BUY \ if submit['side'] == 'BUY' else Side.SELL submit = await self.trader.submit_order( side=side, price=make_price(submit['price']), qty=make_qty(submit['qty']), ioc=submit['ioc'], quote=submit['quote']) else: self.broadcast( 'submit_nack', { 'trigger': { 'msg': 'submit', 'args': req }, 'error': 'One+ fields are invalid!' }) elif 'cancel_session' in req: await self.trader.cancel_session() elif 'cancel_all' in req: await self.trader.cancel_all() elif 'admin' in req: if req['admin'] == 'GetBalance': msg = await self.get_balance_msg() resp.send_str(json.dumps(msg)) elif req['admin'] == 'ListOrders': await self.trader.broadcast_orders() elif req['admin'] == 'GetFills': msg = await self.get_fills_msg() resp.send_str(json.dumps(msg)) else: pass except Exception as e: self.broadcast('UnexpectedError', e) logging.error('Unexpected Error: {}'.format(e)) finally: try: request.app['sockets'].remove(resp) except ValueError: pass return resp
def __init__(self, gateway, instrument): limits = LimitChecker(max_order_qty=make_qty('0.8'), max_order_value=make_price('200.50'), max_open_value=200) self.session = Session(gateway=gateway, instrument=instrument, limits=limits) self.session.add_event_handler(self)
async def on_signal(self, action, update): if not self._enabled: return await self._trader.cancel_all() at_min_spread = self._at_min_spread() book = update['book'] if action == 'BUY': if self._pnl_manager.get_cash_value() <= Decimal(1.00): return cash = Decimal(self._pnl_manager.get_cash_value()) if at_min_spread: price = make_price(float(book['asks'][0]['price'])) qty = Decimal(round(cash / price, 8)) else: price = make_price(float(book['asks'][0]['price']) - 0.01) qty = Decimal(round(cash / price, 8)) await self._jarvis.persistent_submit(side=Side.BID, price=price, qty=make_qty(qty), ioc=False, quote=True) else: if self._pnl_manager.get_crypto_value(book) <= Decimal(0.01): return qty = Decimal(round(self._pnl_manager.crypto_coins, 8)) if at_min_spread: price = make_price(float(book['bids'][0]['price'])) else: price = make_price(float(book['bids'][0]['price']) + 0.01) await self._jarvis.persistent_submit(side=Side.ASK, price=price, qty=make_qty(Decimal(qty)), ioc=False, quote=True) # Notify dashboard listeners await self._broadcast_state("Flipped Signal")
def __init__(self, gateway, instrument): limits = LimitChecker(max_order_qty=make_qty('100'), max_order_value=make_price('20000'), max_open_value=20000) self.session = Session(gateway=gateway, instrument=instrument, limits=limits) self.session.add_event_handler(self) self.orders = [] self._broadcast_cb = None
async def run(self): await self.session.wait_ready() order = await self.submit_order(side=Side.BUY, price=make_price(300), qty=make_qty('0.50')) log.info('Submitted: order={}', order) await asyncio.sleep(3) ioc = await self.submit_ioc(side=Side.BUY, price=make_price(1000), qty=make_qty('0.02')) log.info('Submitted IOC: order={}', ioc) await asyncio.sleep(3) try: if order is not None: await order.cancel() except oe_exceptions.CancelNack as cnack: log.error('{}: {}', cnack.order, cnack) await self.check_balance()
def main(args): loop = asyncio.get_event_loop() strategy_harness = StrategyHarness(loop) params = { 'api_url': gdax.OrderEntryGateway.SANDBOX_URL, 'api_key': args['<API_KEY>'], 'api_secret': args['<API_SECRET>'], 'passphrase': args['<PASSPHRASE>'], 'ip': args['<IP>'], 'port': args['<PORT>'], 'sandbox': False if (args['<SANDBOX>'] == "False") else True, 'instrument': args['<INSTRUMENT>'] } log.info('Starting Aesop Strategy for {} in {} mode', params['instrument'], 'SANDBOX' if params['sandbox'] else 'PRODUCTION') # TODO: Set up limits through configuration StrategyConfig['limits'] = {} StrategyConfig['limits']['max_order_qty'] = make_qty('3') StrategyConfig['limits']['max_order_value'] = make_price('1000') StrategyConfig['limits']['max_open_value'] = 1000 try: loop.run_until_complete(strategy_harness.run(params)) except KeyboardInterrupt: log.info('Keyboard Interrupt - Shutting down Aesop Strategy') # Cancel all running tasks for t in asyncio.Task.all_tasks(): t.cancel() loop.run_forever() # Wait for tasks to finish cleanup. # Gather exceptions. for t in asyncio.Task.all_tasks(): try: t.exception() except Exception: log.exception('Exception during shutdown: {}', t) finally: loop.close()
async def on_gap(self): # Need to manually update the state of every order in existance log.warn('Gapped! Need to request fill status of all orders') tasks = [] for open_order in self._session.open_orders: task = asyncio.ensure_future( self._session.get_fill(open_order.order_id)) tasks.append(task) order_fill_pairs = await asyncio.gather(*tasks) for pairs in order_fill_pairs: for pair in pairs: order = pair[0] fill = pair[1] log.info('Apply fill found after gap: [Order-{}], [Fill-{}]', order, fill) self._session.on_order_fill(order, make_qty(fill['size'])) if order.remaining_qty == 0: self._session.notify_complete(order)
def _compute_orders(self, book, targets): # TODO: Need to test and refactor! # Targets [[price, target crypto], []] # Need to compute order qty # Cannot send more orders than this value # TODO: This should be crypto coins, not value # TODO: When we place and order, make sure that the we # check to see that we have enough coin # to do so. crypto_val = self._pnl_manager.get_crypto_value(book) cash_val = self._pnl_manager.get_cash_value() mkt_price = self._pnl_manager.get_mkt_price(book) strat_value = self._pnl_manager.get_strategy_value(book) crypto_at_mkt_price = crypto_val / strat_value bids = [] asks = [] # handle bids previous_percentage = crypto_at_mkt_price # log.info("previous percentage: {}".format(previous_percentage)) show = self._params['show'] for t in reversed(targets): if t[0] < mkt_price: if show > 0: price = t[0] target_percentage = t[1] # Buy more as we go below our mid point price, # so target should be bigger if previous_percentage > target_percentage: # Need to send out 2 orders # One at mid point and one at price t[0] mkt_target = self._get_target_position(mkt_price) mkt_diff = previous_percentage - mkt_target if mkt_diff > 0: ask_price = book.best_ask.price qty = (mkt_diff * strat_value) / ask_price if (round(make_qty(qty), 2) > 0.0): asks.append( PendingOrder( self._slacked_price(ask_price), self._slacked_qty(qty), Side.ASK)) crypto_val -= ask_price * qty # Own too much-send out an ask order at best bid price diff = target_percentage - mkt_target qty = (diff * strat_value) / price if (round(make_qty(qty), 2) > 0.0): bids.append( PendingOrder(self._slacked_price(price), self._slacked_qty(qty), Side.BID)) cash_val -= price * qty else: diff = target_percentage - previous_percentage qty = (diff * strat_value) / price if (round(make_qty(qty), 2) > 0.0): bids.append( PendingOrder(self._slacked_price(price), self._slacked_qty(qty), Side.BID)) cash_val -= price * qty previous_percentage = target_percentage show -= 1 # handle asks previous_percentage = crypto_at_mkt_price show = self._params['show'] for t in targets: if t[0] > mkt_price: if show > 0: price = t[0] target_percentage = Decimal(t[1]) # Sell more as we go above our mid point price, # so target should be smaller # Handle Best Ask Order Seperately if previous_percentage < target_percentage: # Need to send out 2 orders # one at mid point and one at price t[0] mkt_target = self._get_target_position(mkt_price) mkt_diff = mkt_target - previous_percentage if mkt_diff > 0: bid_price = book.best_bid.price qty = (mkt_diff * strat_value) / bid_price if (round(make_qty(qty), 2) > 0.0): bids.append( PendingOrder( self._slacked_price(bid_price), self._slacked_qty(qty), Side.BID)) cash_val -= bid_price * qty # Own too little-send out a bid order at best bid price diff = mkt_target - target_percentage qty = (diff * strat_value) / price if (round(make_qty(qty), 2) > 0.0): asks.append( PendingOrder(self._slacked_price(price), self._slacked_qty(qty), Side.ASK)) crypto_val -= price * qty else: diff = previous_percentage - target_percentage qty = (diff * strat_value) / price if (round(make_qty(qty), 2) > 0.0): asks.append( PendingOrder(self._slacked_price(price), self._slacked_qty(qty), Side.ASK)) crypto_val -= price * qty previous_percentage = target_percentage show -= 1 # log.info("Asks: {}".format(asks)) # log.info("Bids: {}".format(bids)) return [bids, asks]
def _slacked_qty(self, qty): return round(make_qty(qty), min(self._params['slack'], 8))
def __init__(self, instrument): self._instrument = instrument self.open_long = make_qty(0) self.open_short = make_qty(0) self.base_amount = make_qty(0) self.quote_amount = make_price(0)
def __init__(self, level_side): self._price = make_price(level_side['price']) self._qty = make_qty(level_side['qty'])