def test_candle_wicks(): candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('10000'), Decimal('5000'), Decimal('8000')) assert candle.has_upper_wick() is True assert candle.has_lower_wick() is True candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('8000'), Decimal('8000'), Decimal('8000')) assert candle.has_upper_wick() is False assert candle.has_lower_wick() is False
def test_candle_body_size(): candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('1000'), Decimal('2000'), Decimal('3000'), Decimal('4000')) assert candle.body_size() == Decimal('3000') candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('2000'), Decimal('3000'), Decimal('4000')) assert candle.body_size() == Decimal('4000') candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('10000'), Decimal('5000'), Decimal('8000')) assert candle.body_size() == Decimal('0')
def test_bearish_bullish(): candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('1000'), Decimal('2000'), Decimal('3000'), Decimal('4000')) assert candle.is_bearish() is False assert candle.is_bullish() is True candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('2000'), Decimal('3000'), Decimal('4000')) assert candle.is_bearish() is True assert candle.is_bullish() is False candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('8000'), Decimal('10000'), Decimal('5000'), Decimal('8000')) assert candle.is_bearish() is False assert candle.is_bullish() is False
def test_candle_to_heikin_ashi(): previous_ha_candle = HeikinAshiCandle( '', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('2500'), Decimal('4000'), Decimal('1000'), Decimal('2500'), ) candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('3000'), Decimal('3500'), Decimal('2500'), Decimal('4000')) current_ha_candle = candle_to_heikin_ashi(candle, previous_ha_candle) assert str(current_ha_candle) == '2017-01-01T00:00:00+00:00 ' \ + 'O:2500.00000000 H:3500.00000000 L:2500.00000000 C:3250.00000000 | CandleSize: 1-minute (Heikin-Ashi)'
def _create_order_from_serialized( row: Dict[str, Union[str, int, float, bool]]) -> Order: pair_data = str(row[ORDER_FIELD_PAIR]).split('_') closed_at = None if ORDER_FIELD_CLOSED_AT in row and row[ ORDER_FIELD_CLOSED_AT] is not None: closed_at = dateutil.parser.parse(str( row[ORDER_FIELD_CLOSED_AT])).replace( tzinfo=datetime.timezone.utc) canceled_at = None if ORDER_FIELD_CANCELED_AT in row and row[ ORDER_FIELD_CANCELED_AT] is not None: canceled_at = dateutil.parser.parse( str(row[ORDER_FIELD_CANCELED_AT])).replace( tzinfo=datetime.timezone.utc) return Order( UUID(str(row[ORDER_FIELD_ORDER_ID])), UUID(str(row[ORDER_FIELD_STRATEGY_RUN_ID])), str(row[ORDER_FIELD_MARKET]), str(row[ORDER_FIELD_DIRECTION]), dateutil.parser.parse(str(row['time'])).replace(tzinfo=datetime.timezone.utc), Pair(pair_data[0], pair_data[1]), str(row[ORDER_FIELD_TYPE]), Decimal(row[ORDER_FIELD_QUANTITY]), Decimal(row[ORDER_FIELD_RATE]) if ORDER_FIELD_RATE in row and row[ORDER_FIELD_RATE] is not None else None, str(row[ORDER_FIELD_ID_ON_MARKET]) \ if ORDER_FIELD_ID_ON_MARKET in row and row[ORDER_FIELD_ID_ON_MARKET] \ else None, str(row[ORDER_FIELD_STATUS]), closed_at, canceled_at )
def test_candle(): candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('1000'), Decimal('2000'), Decimal('3000'), Decimal('4000')) assert '2017-01-01T00:00:00+00:00 O:1000.00000000 H:2000.00000000 L:3000.00000000 C:4000.00000000 ' + \ '| CandleSize: 1-minute' == str(candle) assert candle.is_bearish() is False assert candle.is_bullish() is True
def synchronize(ctx: Context, synchronizer_name: str, pair: Tuple[str, str], candle_storage: str) -> None: pair_obj = Pair(pair[0], pair[1]) synchronizer = di_container.synchronizer_plugins.get_synchronizer( synchronizer_name, di_container.candle_storage_plugins.get_candle_storage(candle_storage), di_container.event_emitter ) synchronizer.synchronize(pair_obj)
def get_all_tradable_pairs(self) -> List[Pair]: return [ Pair('USD', 'BTC'), Pair('USD', 'LTC'), Pair('USD', 'ETH'), Pair('USD', 'XMR'), Pair('BTC', 'LTC'), Pair('BTC', 'ETH'), Pair('BTC', 'XMR'), ]
def get_all_tradable_pairs(self) -> List[Pair]: raw_pairs = self._client_v1.get_markets()['result'] result = [] for raw_pair in raw_pairs: if raw_pair['IsActive']: base_currency = self._normalize_currency_code( raw_pair['BaseCurrency']) market_currency = self._normalize_currency_code( raw_pair['MarketCurrency']) result.append(Pair(base_currency, market_currency)) return result
def synchronize(ctx: Context, synchronizer_name: str, market: str, pair: Tuple[str, str], candle_storage: str) -> None: pair_obj = Pair(pair[0], pair[1]) synchronizer = di_container.synchronizer_plugins.get_synchronizer( synchronizer_name, di_container.candle_storage_plugins.get_candle_storage(candle_storage), di_container.event_emitter ) available_markets = synchronizer.get_supported_markets() if market not in available_markets: print_error_and_terminate('Market "{}" is not supported by plugin "{}".'.format(market, synchronizer_name)) synchronizer.synchronize(market, pair_obj)
def test_save_strategy_run_and_find_it( mysql_connection: MySQLdb.Connection) -> None: storage = StrategyRunStorage(mysql_connection) strategy_run_to_save = StrategyRun( UUID('637f46a2-d008-48ba-9899-322abb56b425'), DUMMY_DATE, Pair('USD', 'BTC'), [StrategyRunMarket('yolo_market', 'yolo_plugin_name', {'foo': 'BAR'})], 'strategy_dummy_name', {'gandalf': 'Gandalf the Gray'}, DateTimeInterval(DUMMY_DATE, None), 'candle_dummy_storage', 'order_dummy_storage') storage.insert(strategy_run_to_save) strategy_runs = storage.find_by() assert len(strategy_runs) == 1 assert str(strategy_runs[0].strategy_run_id) == str( strategy_run_to_save.strategy_run_id)
def export_orders( ctx: Context, market_name, pair: Tuple[str, str], interval: Tuple[str, str], output_file: str, order_storage: str ) -> None: storage = di_container.order_storage_plugins.get_order_storage(order_storage) pair_obj = Pair(pair[0], pair[1]) interval_obj = DateTimeInterval( dateutil.parser.parse(interval[0]).replace(tzinfo=datetime.timezone.utc), dateutil.parser.parse(interval[1]).replace(tzinfo=datetime.timezone.utc) ) exporter = OrderExporter(storage) exporter.export_to_file(output_file, market_name, pair_obj, interval_obj)
def test_order_export_import(): pair = Pair('USD', 'BTC') order = Order( UUID('16fd2706-8baf-433b-82eb-8c7fada847da'), UUID('99fd2706-8baf-433b-82eb-8c7fada847da'), DUMMY_MARKET, DIRECTION_BUY, datetime.datetime(2017, 11, 26, 10, 11, 12, tzinfo=datetime.timezone.utc), pair, ORDER_TYPE_LIMIT, Decimal('1'), Decimal('8000'), 'aaa-id-from-market' ) storage = flexmock() storage.should_receive('find_by').and_return([order]).once() storage.should_receive('save_order').once() exporter = OrderExporter(storage) file_name = os.path.dirname(__file__) + '_orders.json' exporter.export_to_file(file_name, 'dummy_market', pair) expected = [{ "order_id": "16fd2706-8baf-433b-82eb-8c7fada847da", "strategy_run_id": "99fd2706-8baf-433b-82eb-8c7fada847da", "market": "dummy_market_name", "direction": "buy", "created_at": "2017-11-26T10:11:12+00:00", "pair": "USD_BTC", "type": "limit", "quantity": "1", "rate": "8000", "id_on_market": "aaa-id-from-market", "status": "open", "closed_at": None, "canceled_at": None }] with open(file_name) as json_file: assert json.load(json_file) == expected exporter.import_from_file(file_name) os.remove(file_name)
def run_strategy( ctx: Context, strategy_name: str, pair: Tuple[str, str], market_names: Tuple[str], configuration_file: Union[str, None], candle_storage: str, order_storage: str, market_plugin: str ) -> None: pair_obj = Pair(pair[0], pair[1]) strategy_configuration: Dict = {} if configuration_file is not None: strategy_configuration = load_configuration_from_file(configuration_file) strategy_run_at = di_container.datetime_factory.now() strategy_run = StrategyRun( uuid.uuid4(), strategy_run_at, pair_obj, [StrategyRunMarket(market_plugin, market_name, {}) for market_name in market_names], strategy_name, strategy_configuration, DateTimeInterval(strategy_run_at, None), candle_storage, order_storage ) di_container.strategy_run_storage.insert(strategy_run) di_container.event_emitter.emit_new_strategy_run(strategy_run) try: di_container.strategy_standard_runner.run(strategy_run) except StrategyNotProvidedByAnyPluginException as e: _terminate_strategy_run(strategy_run) print_error_and_terminate(str(e)) except ForEndUserException as e: _terminate_strategy_run(strategy_run) print_error_and_terminate(str(e)) except KeyboardInterrupt: _terminate_strategy_run(strategy_run) pass
def test_find_by(influx_database: InfluxDBClient): storage = OrderInnoDbStorage(influx_database, 'test_orders') orders = storage.find_by(market_name=DUMMY_MARKET, pair=BTC_USD_PAIR) assert orders == [] create_dummy_data(influx_database) orders = storage.find_by(market_name=DUMMY_MARKET, pair=BTC_USD_PAIR, status=ORDER_STATUS_OPEN) assert len(orders) == 1 assert orders[0].is_open is True assert str(orders[0].order_id) == '16fd2706-8baf-433b-82eb-8c7fada847da' orders = storage.find_by(market_name=DUMMY_MARKET, pair=BTC_USD_PAIR, status=ORDER_STATUS_CLOSED) assert len(orders) == 1 assert orders[0].is_open is False assert str(orders[0].order_id) == '16fd2706-8baf-433b-82eb-8c7fada847db' orders = storage.find_by(market_name='yolo', pair=BTC_USD_PAIR) assert orders == [] orders = storage.find_by(market_name=DUMMY_MARKET, pair=Pair('FOO', 'BAR')) assert orders == [] orders = storage.find_by(market_name=DUMMY_MARKET, pair=BTC_USD_PAIR, direction=DIRECTION_BUY) assert len(orders) == 1 assert orders[0].is_buy() is True assert orders[0].is_sell() is False assert str(orders[0].order_id) == '16fd2706-8baf-433b-82eb-8c7fada847da' orders = storage.find_by(market_name=DUMMY_MARKET, pair=BTC_USD_PAIR, direction=DIRECTION_SELL) assert len(orders) == 1 assert orders[0].is_buy() is False assert orders[0].is_sell() is True assert str(orders[0].order_id) == '16fd2706-8baf-433b-82eb-8c7fada847db' orders = storage.find_by( market_name=DUMMY_MARKET, pair=BTC_USD_PAIR, strategy_run_id='99fd2706-8baf-433b-82eb-8c7fada847da' ) assert len(orders) == 1 assert str(orders[0].strategy_run_id) == '99fd2706-8baf-433b-82eb-8c7fada847da'
def test_market(): market = MockMarket( CurrentUtcDateTimeFactory(), { 'mocked_market_name': 'yolo', 'mocked_base_currency_balance': Decimal('1001'), 'mocked_base_currency': 'WTF', 'mocked_transaction_maker_fee': Decimal('0.001'), 'mocked_transaction_taker_fee': Decimal('0.001'), }) assert 'yolo' == market.name assert Decimal('0.004') == market.get_pair_market_info( BTC_USD_PAIR).minimal_order_size assert '1001.00000000 WTF' == str(market.get_balance('WTF')) assert '0.00000000 LOL' == str(market.get_balance('LOL')) assert Decimal('0.001') == market.transaction_taker_fee assert Decimal('0.001') == market.transaction_maker_fee order = create_order(pair=Pair('WTF', 'BTC'), quantity=Decimal('0.1001')) assert order == market.place_order(order) assert market.cancel_order('xxx') is None assert str(market.get_balances() ) == '[0.00000000 WTF, 0.00000000 LOL, 0.09999990 BTC]'
def test_serialize_strategy() -> None: strategy_run_market = StrategyRun( UUID('8b3213c8-2c07-4283-8197-a9babfcc1ec8'), DUMMY_DATE, Pair('USD', 'BTC'), [], 'strategy_xyz', {}, DateTimeInterval(), 'c', 'o' ) assert serialize_strategy_run(strategy_run_market) == { 'candle_storage_name': 'c', 'interval': {'since': None, 'till': None}, 'markets': [], 'order_storage_name': 'o', 'pair': 'USD_BTC', 'run_at': '2017-11-26T10:11:12+00:00', 'strategy_configuration': {}, 'strategy_name': 'strategy_xyz', 'strategy_run_id': '8b3213c8-2c07-4283-8197-a9babfcc1ec8', }
def test_candle_export_import(): pair = Pair('USD', 'BTC') candle = Candle( 'dummy_market', pair, datetime.datetime(2017, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc), Decimal('1000'), Decimal('2000'), Decimal('3000'), Decimal('4000') ) storage = flexmock() storage.should_receive('find_by').and_return([candle]).once() storage.should_receive('write_candles').once() exporter = CandleExporter(storage) file_name = os.path.dirname(__file__) + '_orders.json' exporter.export_to_file(file_name, 'dummy_market', pair) expected = [{ 'market': 'dummy_market', 'pair': 'USD_BTC', 'time': '2017-01-01T00:00:00+00:00', 'open': "1000.00000000", 'high': "2000.00000000", 'low': "3000.00000000", 'close': "4000.00000000", 'size': '1-minute', }] with open(file_name) as json_file: assert json.load(json_file) == expected exporter.import_from_file(file_name) os.remove(file_name)
import copy import datetime from uuid import UUID from decimal import Decimal from coinrat.domain.pair import Pair from coinrat.domain.order import Order, ORDER_TYPE_LIMIT, OrderMarketInfo, DIRECTION_BUY DUMMY_ORDER_OPEN = Order( UUID('16fd2706-8baf-433b-82eb-8c7fada847db'), UUID('99fd2706-8baf-433b-82eb-8c7fada847da'), 'lorem_ipsum', DIRECTION_BUY, datetime.datetime(2017, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc), Pair('USD', 'BTC'), ORDER_TYPE_LIMIT, Decimal('2'), Decimal('9000'), 'bbb-id-from-market', ) def test_open_order(): order = DUMMY_ORDER_OPEN expected = 'BUY-OPEN, ' \ + 'Id: "16fd2706-8baf-433b-82eb-8c7fada847db", ' \ + 'Market: "lorem_ipsum", ' \ + 'Created: "2017-01-02T03:04:05+00:00", ' \ + 'Closed: "None", ' \
def test_get_pair_market_info_invalid_pair(): with pytest.raises(MarketPairDoesNotExistsException): bittrex_market_factory('', '').get_pair_market_info(Pair('YOLO', 'SWAG'))
def test_pair_market_info(): info = PairMarketInfo(Pair('USD', 'BTC'), Decimal('0.0003')) assert 'Pair: [USD_BTC], minimal order size: 0.0003' == str(info)
def test_subscription_can_be_found(): storage = SubscriptionStorage() last_candle_subscription = LastCandleSubscription( '1', 'foo_storage', 'bar_market', Pair('USD', 'BTC'), CandleSize(CANDLE_SIZE_UNIT_MINUTE, 1) ) storage.subscribe(last_candle_subscription) subscription_interval = DateTimeInterval( datetime.datetime(2018, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc), datetime.datetime(2018, 1, 2, 0, 0, 0, tzinfo=datetime.timezone.utc) ) date_in_interval = datetime.datetime(2018, 1, 1, 12, 0, 0, tzinfo=datetime.timezone.utc) date_outside_interval = datetime.datetime(2018, 1, 3, 0, 0, tzinfo=datetime.timezone.utc) new_order_subscription = NewOrderSubscription( '1', 'foo_storage', 'bar_market', Pair('USD', 'BTC'), subscription_interval ) storage.subscribe(new_order_subscription) assert storage.find_subscriptions_for_event('unknown_event_name') == [] candle_suitable_for_subscription = Candle( 'bar_market', Pair('USD', 'BTC'), date_in_interval, Decimal('11000'), Decimal('11000'), Decimal('11000'), Decimal('11000') ) assert storage.find_subscriptions_for_event(EVENT_LAST_CANDLE_UPDATED)[0] == last_candle_subscription assert storage.find_subscriptions_for_event( EVENT_LAST_CANDLE_UPDATED, {'storage': 'foo_storage', 'candle': serialize_candle(candle_suitable_for_subscription)} )[0] == last_candle_subscription assert storage.find_subscriptions_for_event( EVENT_LAST_CANDLE_UPDATED, {'storage': 'gandalf', 'candle': serialize_candle(candle_suitable_for_subscription)} ) == [] assert storage.find_subscriptions_for_event( EVENT_LAST_CANDLE_UPDATED, { 'storage': 'foo_storage', 'candle': serialize_candle( Candle( 'bar_market', Pair('OMG', 'WTF'), date_in_interval, Decimal('11000'), Decimal('11000'), Decimal('11000'), Decimal('11000') ) ) } ) == [] assert storage.find_subscriptions_for_event( EVENT_LAST_CANDLE_UPDATED, { 'storage': 'foo_storage', 'candle': serialize_candle( Candle( 'wtf_market', Pair('USD', 'BTC'), date_in_interval, Decimal('11000'), Decimal('11000'), Decimal('11000'), Decimal('11000') ) ) } ) == [] order_suitable_for_subscription = _crate_serialized_order(Pair('USD', 'BTC'), 'bar_market', date_in_interval) assert storage.find_subscriptions_for_event(EVENT_NEW_ORDER)[0] == new_order_subscription assert storage.find_subscriptions_for_event( EVENT_NEW_ORDER, {'storage': 'foo_storage', 'order': order_suitable_for_subscription} )[0] == new_order_subscription assert storage.find_subscriptions_for_event( EVENT_NEW_ORDER, {'storage': 'gandalf', 'order': order_suitable_for_subscription} ) == [] assert storage.find_subscriptions_for_event( EVENT_NEW_ORDER, { 'storage': 'foo_storage', 'order': _crate_serialized_order(Pair('USD', 'BTC'), 'bar_market', date_outside_interval) } ) == [] assert storage.find_subscriptions_for_event( EVENT_NEW_ORDER, { 'storage': 'foo_storage', 'order': _crate_serialized_order(Pair('OMG', 'WTF'), 'bar_market', date_in_interval) } ) == [] assert storage.find_subscriptions_for_event( EVENT_NEW_ORDER, { 'storage': 'foo_storage', 'order': _crate_serialized_order(Pair('USD', 'BTC'), 'wtf_market', date_in_interval) } ) == [] storage.unsubscribe(EVENT_NEW_ORDER, '2') assert storage.find_subscriptions_for_event(EVENT_NEW_ORDER)[0] == new_order_subscription storage.unsubscribe(EVENT_NEW_ORDER, '1') assert storage.find_subscriptions_for_event(EVENT_NEW_ORDER) == [] storage.unsubscribe(EVENT_LAST_CANDLE_UPDATED, '2') assert storage.find_subscriptions_for_event(EVENT_LAST_CANDLE_UPDATED)[0] == last_candle_subscription storage.unsubscribe(EVENT_LAST_CANDLE_UPDATED, '1') assert storage.find_subscriptions_for_event(EVENT_LAST_CANDLE_UPDATED) == []
import pytest from flexmock import flexmock from coinrat_cryptocompare.synchronizer import CryptocompareSynchronizer, CryptocompareRequestException, \ ALL_EXCHANGES_URL from coinrat.domain.pair import Pair from coinrat.event.event_emitter import EventEmitter BTC_USD_PAIR = Pair('USD', 'BTC') DUMMY_CANDLE_DATA = [{ 'time': 1511608020, 'close': 8403.35, 'high': 8403.35, 'low': 8403, 'open': 8403, 'volumefrom': 1.09, 'volumeto': 9197.77 }, { 'time': 1511608080, 'close': 8403.35, 'high': 8403.35, 'low': 8403.35, 'open': 8403.35, 'volumefrom': 0, 'volumeto': 0 }] def test_synchronize_success(): session = flexmock()
def test_create_initial_heikin_ashi_candle(): candle = Candle('', Pair('USD', 'BTC'), DUMMY_DATE, Decimal('2000'), Decimal('4500'), Decimal('1000'), Decimal('3000')) ha_candle = create_initial_heikin_ashi_candle(candle) assert str(ha_candle) == '2017-01-01T00:00:00+00:00 ' \ + 'O:2500.00000000 H:4500.00000000 L:1000.00000000 C:2625.00000000 | CandleSize: 1-minute (Heikin-Ashi)'