def find_by( self, market_name: str, pair: Pair, interval: DateTimeInterval = DateTimeInterval(None, None), candle_size: CandleSize = CandleSize(CANDLE_SIZE_UNIT_MINUTE, 1) ) -> List[Candle]: parameters = { CANDLE_STORAGE_FIELD_MARKET: "= '{}'".format(market_name), CANDLE_STORAGE_FIELD_PAIR: "= '{}'".format(serialize_pair(pair)), } if interval.since is not None: parameters['"time" >'] = "'{}'".format(interval.since.isoformat()) if interval.till is not None: parameters['"time" <'] = "'{}'".format(interval.till.isoformat()) select = '*' if not candle_size.is_one_minute(): select = 'FIRST("open") AS "open", MAX("high") AS "high", MIN("low") AS "low", LAST("close") AS "close"' sql = 'SELECT {} FROM "{}" WHERE '.format(select, MEASUREMENT_CANDLES_NAME) where = [] for key, value in parameters.items(): where.append('{} {}'.format(key, value)) sql += ' AND '.join(where) sql += self._get_group_by(candle_size) result: ResultSet = self._client.query(sql) data = list(result.get_points()) return self._parse_db_result_into_candles(data, market_name, pair, candle_size)
def serialize_order(order: Order) -> Dict[str, Union[str, None]]: return { ORDER_FIELD_ORDER_ID: str(order.order_id), ORDER_FIELD_STRATEGY_RUN_ID: str(order.strategy_run_id), ORDER_FIELD_MARKET: order.market_name, ORDER_FIELD_DIRECTION: order._direction, ORDER_FIELD_CREATED_AT: order.created_at.isoformat(), ORDER_FIELD_PAIR: serialize_pair(order.pair), ORDER_FIELD_TYPE: order.type, ORDER_FIELD_QUANTITY: str(order.quantity), ORDER_FIELD_RATE: str(order.rate), ORDER_FIELD_ID_ON_MARKET: order.id_on_market, ORDER_FIELD_STATUS: order._status, ORDER_FIELD_CLOSED_AT: order.closed_at.isoformat() if order.closed_at is not None else None, ORDER_FIELD_CANCELED_AT: order.canceled_at.isoformat() if order.canceled_at is not None else None, }
def _get_serialized_order(self, order: Order) -> Dict: return { 'measurement': self._measurement_name, 'tags': { ORDER_FIELD_MARKET: order.market_name, ORDER_FIELD_PAIR: serialize_pair(order.pair), ORDER_FIELD_ORDER_ID: str(order.order_id), ORDER_FIELD_STRATEGY_RUN_ID: str(order.strategy_run_id), }, 'time': order.created_at.isoformat(), 'fields': { ORDER_FIELD_DIRECTION: order._direction, ORDER_FIELD_ID_ON_MARKET: order.id_on_market, ORDER_FIELD_TYPE: order.type, ORDER_FIELD_STATUS: order._status, # Todo: figure out how to store decimals in influx (maybe int -> *100000) ORDER_FIELD_QUANTITY: float(order.quantity), ORDER_FIELD_RATE: float(order.rate), ORDER_FIELD_CLOSED_AT: order.closed_at.isoformat() if order.closed_at is not None else None, ORDER_FIELD_CANCELED_AT: order.canceled_at.isoformat() if order.canceled_at is not None else None, } }
def _fix_fields_in_raw_candle(raw_candle: Dict, market_name: str, pair: Pair, candle_size: CandleSize) -> Dict: if CANDLE_STORAGE_FIELD_MARKET not in raw_candle: raw_candle[CANDLE_STORAGE_FIELD_MARKET] = market_name if CANDLE_STORAGE_FIELD_PAIR not in raw_candle: raw_candle[CANDLE_STORAGE_FIELD_PAIR] = serialize_pair(pair) if CANDLE_STORAGE_FIELD_SIZE not in raw_candle: raw_candle[CANDLE_STORAGE_FIELD_SIZE] = serialize_candle_size( candle_size) return raw_candle
def serialize_candle(candle: Candle) -> Dict[str, str]: return { CANDLE_STORAGE_FIELD_MARKET: candle.market_name, CANDLE_STORAGE_FIELD_PAIR: serialize_pair(candle.pair), CANDLE_STORAGE_FIELD_TIME: candle.time.isoformat(), CANDLE_STORAGE_FIELD_OPEN: '{0:.8f}'.format(candle.open), CANDLE_STORAGE_FIELD_HIGH: '{0:.8f}'.format(candle.high), CANDLE_STORAGE_FIELD_LOW: '{0:.8f}'.format(candle.low), CANDLE_STORAGE_FIELD_CLOSE: '{0:.8f}'.format(candle.close), CANDLE_STORAGE_FIELD_SIZE: serialize_candle_size(candle.candle_size), }
def serialize_strategy_run(strategy_run: StrategyRun): return { 'strategy_run_id': str(strategy_run.strategy_run_id), 'run_at': strategy_run.run_at.isoformat(), 'pair': serialize_pair(strategy_run.pair), 'markets': serialize_strategy_run_markets(strategy_run.markets), 'strategy_name': strategy_run.strategy_name, 'strategy_configuration': strategy_run.strategy_configuration, 'interval': serialize_datetime_interval(strategy_run.interval), 'candle_storage_name': strategy_run.candle_storage_name, 'order_storage_name': strategy_run.order_storage_name, }
def get_last_minute_candle(self, market_name: str, pair: Pair, current_time: datetime.datetime) -> Candle: sql = ''' SELECT * FROM "{}" WHERE "pair"='{}' AND "market"='{}' AND "time" <= '{}' ORDER BY "time" DESC LIMIT 1 '''.format(MEASUREMENT_CANDLES_NAME, serialize_pair(pair), market_name, current_time.isoformat()) result: ResultSet = self._client.query(sql) result = list(result.get_points()) self._validate_result_has_some_data(market_name, result) return deserialize_candle(result[0])
def find_last_order(self, market_name: str, pair: Pair) -> Union[Order, None]: sql = ''' SELECT * FROM "{}" WHERE "pair"='{}' AND "market"='{}' ORDER BY "time" DESC LIMIT 1 '''.format(self._measurement_name, serialize_pair(pair), market_name) result: ResultSet = self._client.query(sql) result = list(result.get_points()) if len(result) == 0: return None return self._create_order_from_serialized(result[0])
def mean( self, market_name: str, pair: Pair, field: str, interval: DateTimeInterval = DateTimeInterval(None, None) ) -> Decimal: sql = ''' SELECT MEAN("{}") AS "field_mean" FROM "{}" WHERE "time" > '{}' AND "time" < '{}' AND "pair"='{}' AND "market"='{}' GROUP BY "{}" '''.format(field, MEASUREMENT_CANDLES_NAME, interval.since.isoformat(), interval.till.isoformat(), serialize_pair(pair), market_name, field) result: ResultSet = self._client.query(sql) self._validate_result_has_some_data(market_name, result) mean = list(result.items()[0][1])[0]['field_mean'] return Decimal(mean)
def _create_point_data(candle: Candle): return { 'measurement': MEASUREMENT_CANDLES_NAME, 'tags': { 'market': candle.market_name, 'pair': serialize_pair(candle.pair), }, 'time': candle.time.isoformat(), 'fields': { CANDLE_STORAGE_FIELD_OPEN: float(candle.open), CANDLE_STORAGE_FIELD_CLOSE: float(candle.close), CANDLE_STORAGE_FIELD_LOW: float(candle.low), CANDLE_STORAGE_FIELD_HIGH: float(candle.high), CANDLE_STORAGE_FIELD_SIZE: serialize_candle_size(candle.candle_size) } }
def _insert(cursor, strategy_run: StrategyRun) -> None: cursor.execute(""" INSERT INTO `strategy_runs` ( `id`, `run_at`, `pair`, `markets`, `strategy_name`, `strategy_configuration`, `interval_since`, `interval_till`, `candle_storage_name`, `order_storage_name` ) VALUES ( %s, %s, %s, %s, %s, %s, %s, %s, %s, %s ) """, ( str(strategy_run.strategy_run_id), strategy_run.run_at.timestamp(), serialize_pair(strategy_run.pair), json.dumps(serialize_strategy_run_markets(strategy_run.markets)), strategy_run.strategy_name, json.dumps(strategy_run.strategy_configuration), strategy_run.interval.since.timestamp(), strategy_run.interval.till.timestamp() if strategy_run.interval.till is not None else None, strategy_run.candle_storage_name, strategy_run.order_storage_name ))
def find_by(self, market_name: str, pair: Pair, status: Union[str, None] = None, direction: Union[str, None] = None, interval: DateTimeInterval = DateTimeInterval(None, None), strategy_run_id: Union[str, None] = None) -> List[Order]: assert status in POSSIBLE_ORDER_STATUSES or status is None, 'Invalid status: "{}"'.format( status) parameters = { ORDER_FIELD_MARKET: "= '{}'".format(market_name), ORDER_FIELD_PAIR: "= '{}'".format(serialize_pair(pair)), } if status is not None: parameters[ORDER_FIELD_STATUS] = "= '{}'".format(status) if direction is not None: parameters[ORDER_FIELD_DIRECTION] = "= '{}'".format(direction) if interval.since is not None: parameters['"time" >'] = "'{}'".format(interval.since.isoformat()) if interval.till is not None: parameters['"time" <'] = "'{}'".format(interval.till.isoformat()) if strategy_run_id is not None: parameters[ORDER_FIELD_STRATEGY_RUN_ID] = "= '{}'".format( strategy_run_id) sql = 'SELECT * FROM "{}" WHERE '.format(self._measurement_name) where = [] for key, value in parameters.items(): where.append('{} {}'.format(key, value)) sql += ' AND '.join(where) result: ResultSet = self._client.query(sql) data = list(result.get_points()) return [self._create_order_from_serialized(row) for row in data]
def pairs(sid, data): logger.info('RECEIVED: {}, {}'.format(EVENT_GET_PAIRS, data)) if 'market_name' not in data: return 'ERROR', { 'message': 'Missing "market_name" field in request.' } if 'market_plugin_name' not in data: return 'ERROR', { 'message': 'Missing "market_plugin_name" field in request.' } market_plugin = self._market_plugins.get_plugin( data['market_plugin_name']) market = market_plugin.get_market(data['market_name'], datetime_factory, {}) return 'OK', list( map( lambda pair: { 'key': serialize_pair(pair), 'name': pair.base_currency + '-' + pair.market_currency }, market.get_all_tradable_pairs()))
def get_current_price(self, pair: Pair) -> Decimal: return self._current_prices[serialize_pair(pair)]
def mock_current_price(self, pair: Pair, value: Decimal) -> None: self._current_prices[serialize_pair(pair)] = value