def test_number_of_markets_validation(error: bool, markets: List[Union[Market, Mock]]): candle_storage = flexmock() candle_storage.should_receive('mean').and_return(0).mock() candle_storage.should_receive('get_last_minute_candle').and_return( flexmock(average_price=Decimal('8000'))) if len( markets ) == 1: # Flexmock is not working properly with @pytest.mark.parametrize (MethodSignatureError) markets = [ markets[0].should_receive('name').and_return( DUMMY_MARKET_NAME).mock() ] order_storage = create_order_storage_mock() order_storage.should_receive('find_by').and_return([]) order_storage.should_receive('find_last_order').and_return(None) strategy = DoubleCrossoverStrategy( candle_storage, OrderFacade(order_storage, create_portfolio_snapshot_mock(), create_event_emitter_mock()), CurrentUtcDateTimeFactory(), STRATEGY_RUN) if error: with pytest.raises(StrategyConfigurationException): strategy.tick(markets) else: strategy.tick(markets)
def test_not_enough_balance_logs_warning(): candle_storage = flexmock() candle_storage.should_receive('mean').and_return(8000).and_return( 7900).and_return(8000).and_return(8100) candle_storage.should_receive('get_last_minute_candle').and_return( flexmock(average_price=Decimal(Decimal('8000')))) market = create_market_mock() market.should_receive('place_order').and_raise( NotEnoughBalanceToPerformOrderException) market.should_receive('get_balances').and_return([]) order_storage = create_order_storage_mock() order_storage.should_receive('find_by').and_return([]) order_storage.should_receive('find_last_order').and_return(None) strategy = DoubleCrossoverStrategy( candle_storage, OrderFacade(order_storage, create_portfolio_snapshot_mock(), create_event_emitter_mock()), CurrentUtcDateTimeFactory(), STRATEGY_RUN) flexmock(logging.getLogger('coinrat_double_crossover_strategy.strategy') ).should_receive('warning').once() strategy.tick([market]) strategy.tick([market])
def test_mock_market_current_price(): market = MockMarket(CurrentUtcDateTimeFactory(), {'mocked_market_name': 'yolo_market'}) with pytest.raises(KeyError): market.get_current_price(BTC_USD_PAIR) market.mock_current_price(BTC_USD_PAIR, Decimal('9854.458')) assert market.get_current_price(BTC_USD_PAIR) == Decimal('9854.458')
def test_sending_signal( expected_buy: int, expected_sell: int, canceled_orders_count: int, mean_evolution: List[Tuple[int, int]], previous_order_rate: Union[int, None], current_candle_average_price: int, ): candle_storage = flexmock() expectation = candle_storage.should_receive('mean') for mean in mean_evolution: expectation.and_return(mean[0]).and_return(mean[1]) candle_storage.should_receive('get_last_minute_candle').and_return( flexmock(average_price=Decimal(current_candle_average_price))) market = create_market_mock() class OrderDirectionMatcher(object): def __init__(self, direction): self._direction = direction def __eq__(self, order: Order): return self._direction == order._direction market.should_receive('place_order') \ .with_args(OrderDirectionMatcher(DIRECTION_BUY)) \ .and_return(DUMMY_CLOSED_ORDER) \ .times(expected_buy) market.should_receive('place_order') \ .with_args(OrderDirectionMatcher(DIRECTION_SELL)) \ .and_return(DUMMY_CLOSED_ORDER) \ .times(expected_sell) market.should_receive('cancel_order').with_args( DUMMY_OPEN_ORDER.id_on_market).times(canceled_orders_count) market.should_receive('get_order_status').and_return(STILL_OPEN_ORDER_INFO) market.should_receive('get_balances').and_return([]) order_storage = flexmock(name='yolo_order_storage') order_storage.should_receive('find_by').and_return([]) order_storage.should_receive('find_by').and_return([DUMMY_OPEN_ORDER]) order_storage.should_receive('find_by').and_return([DUMMY_OPEN_ORDER]) order_storage.should_receive('save_order').times(expected_buy + expected_sell + canceled_orders_count) order_storage.should_receive('delete') previous_order = None if previous_order_rate is not None: previous_order = flexmock(rate=Decimal(previous_order_rate)) order_storage.should_receive('find_last_order').and_return(previous_order) strategy = DoubleCrossoverStrategy( candle_storage, OrderFacade(order_storage, create_portfolio_snapshot_mock(), create_event_emitter_mock()), CurrentUtcDateTimeFactory(), STRATEGY_RUN) for x in range(0, len(mean_evolution)): strategy.tick([market])
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_closes_open_orders_if_closed_on_market( expected_save_order_called: int, markets_order_info: OrderMarketInfo): candle_storage = flexmock() candle_storage.should_receive('mean').and_return(8000).and_return(7900) candle_storage.should_receive('get_last_minute_candle').and_return( flexmock(average_price=Decimal(Decimal('8000')))) order_storage = create_order_storage_mock() order_storage.should_receive('find_by').and_return([DUMMY_OPEN_ORDER]) order_storage.should_receive('delete') order_storage.should_receive('save_order').times( expected_save_order_called) market = create_market_mock() market.should_receive('get_order_status').and_return( markets_order_info).once() market.should_receive('get_balances').and_return([]) strategy = DoubleCrossoverStrategy( candle_storage, OrderFacade(order_storage, create_portfolio_snapshot_mock(), create_event_emitter_mock()), CurrentUtcDateTimeFactory(), STRATEGY_RUN) strategy.tick([market])
def test_market_processes_orders(): market = MockMarket(CurrentUtcDateTimeFactory(), {'mocked_market_name': 'yolo_market'}) assert market.get_balance('USD').available_amount == Decimal('1000') with pytest.raises(NotEnoughBalanceToPerformOrderException): market.place_order(create_order()) assert market.get_balance('USD').available_amount == Decimal('1000') market.place_order(create_order(quantity=Decimal('0.1'))) assert market.get_balance('USD').available_amount == Decimal('0') assert market.get_balance('BTC').available_amount == Decimal('0.09975') with pytest.raises(NotEnoughBalanceToPerformOrderException): market.place_order( create_order(direction=DIRECTION_SELL, quantity=Decimal('0.1'))) market.place_order( create_order(direction=DIRECTION_SELL, quantity=Decimal('0.09975'))) assert market.get_balance('USD').available_amount == Decimal( '995.00625') # fee applied twice assert market.get_balance('BTC').available_amount == Decimal('0')
def __init__(self) -> None: super().__init__() self._storage = { 'candle_storage_plugins': { 'instance': None, 'factory': lambda: CandleStoragePlugins(), }, 'order_storage_plugins': { 'instance': None, 'factory': lambda: OrderStoragePlugins(), }, 'market_plugins': { 'instance': None, 'factory': self._create_market_plugins, }, 'synchronizer_plugins': { 'instance': None, 'factory': lambda: SynchronizerPlugins(), }, 'strategy_plugins': { 'instance': None, 'factory': lambda: StrategyPlugins(), }, 'portfolio_snapshot_storage_plugins': { 'instance': None, 'factory': lambda: PortfolioSnapshotStoragePlugins(), }, 'rabbit_connection': { 'instance': None, 'factory': self._create_rabbit_connection, }, 'event_emitter': { 'instance': None, 'factory': self._create_event_emitter, }, 'task_planner': { 'instance': None, 'factory': lambda: TaskPlanner(self._get_factory('rabbit_connection')), }, 'datetime_factory': { 'instance': None, 'factory': lambda: CurrentUtcDateTimeFactory(), }, 'socket_server': { 'instance': None, 'factory': lambda: SocketServer(self.task_planner, self.datetime_factory, self. candle_storage_plugins, self. order_storage_plugins, self.market_plugins, self. strategy_plugins, self.strategy_run_storage, self. portfolio_snapshot_storage_plugins), }, 'strategy_replayer': { 'instance': None, 'factory': lambda: StrategyReplayer( self.candle_storage_plugins, self.order_storage_plugins, self.strategy_plugins, self.market_plugins, self. portfolio_snapshot_storage_plugins, self.event_emitter) }, 'task_consumer': { 'instance': None, 'factory': lambda: TaskConsumer(self.rabbit_connection, self.strategy_replayer, self.datetime_factory, self.strategy_run_storage, self.event_emitter), }, 'subscription_storage': { 'instance': None, 'factory': lambda: SubscriptionStorage(), }, 'mysql_connection': { 'instance': None, 'factory': lambda: MySQLdb.connect( host=os.environ.get('MYSQL_HOST'), database=os.environ.get('MYSQL_DATABASE'), user=os.environ.get('MYSQL_USER'), password=os.environ.get('MYSQL_PASSWORD'), ), }, 'strategy_run_storage': { 'instance': None, 'factory': lambda: StrategyRunStorage(self.mysql_connection), }, 'strategy_standard_runner': { 'instance': None, 'factory': lambda: StrategyStandardRunner( self.candle_storage_plugins, self.order_storage_plugins, self.strategy_plugins, self.market_plugins, self.portfolio_snapshot_storage_plugins, self.event_emitter, self.datetime_factory, ), } }
def test_get_tradable_pairs(): market = MockMarket(CurrentUtcDateTimeFactory(), {'mocked_market_name': 'yolo_market'}) pairs = market.get_all_tradable_pairs() assert len(pairs) > 0
def test_market_get_order_status(): market = MockMarket(CurrentUtcDateTimeFactory(), {'mocked_market_name': 'yolo_market'}) status = market.get_order_status(create_order()) assert 'Order Id: "16fd2706-8baf-433b-82eb-8c7fada847da", OPEN, Closed at: "", Remaining quantity: "0"' \ == str(status)