def test_can_create_order(self):
        config, exchange, trader, symbol = self._get_tools()
        portfolio = trader.get_portfolio()
        # portfolio: "BTC": 10 "USD": 1000
        not_owned_symbol = "ETH/BTC"
        not_owned_market = "BTC/ETH"
        min_trigger_symbol = "SUB/BTC"
        min_trigger_market = "ADA/BNB"

        # order from neutral state => false
        assert not AbstractTradingModeCreator(None).can_create_order(
            symbol, exchange, EvaluatorStates.NEUTRAL, portfolio)

        # sell order using a currency with 0 available
        assert not AbstractTradingModeCreator(None).can_create_order(
            not_owned_symbol, exchange, EvaluatorStates.SHORT, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            not_owned_symbol, exchange, EvaluatorStates.VERY_SHORT, portfolio)

        # sell order using a currency with < min available
        assert not AbstractTradingModeCreator(None).can_create_order(
            min_trigger_symbol, exchange, EvaluatorStates.SHORT, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            min_trigger_symbol, exchange, EvaluatorStates.VERY_SHORT,
            portfolio)

        # sell order using a currency with > min available
        assert AbstractTradingModeCreator(None).can_create_order(
            not_owned_market, exchange, EvaluatorStates.SHORT, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            not_owned_market, exchange, EvaluatorStates.VERY_SHORT, portfolio)

        # buy order using a market with 0 available
        assert not AbstractTradingModeCreator(None).can_create_order(
            not_owned_market, exchange, EvaluatorStates.LONG, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            not_owned_market, exchange, EvaluatorStates.VERY_LONG, portfolio)

        # buy order using a market with < min available
        assert not AbstractTradingModeCreator(None).can_create_order(
            min_trigger_market, exchange, EvaluatorStates.LONG, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            min_trigger_market, exchange, EvaluatorStates.VERY_LONG, portfolio)

        # buy order using a market with > min available
        assert AbstractTradingModeCreator(None).can_create_order(
            not_owned_symbol, exchange, EvaluatorStates.LONG, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            not_owned_symbol, exchange, EvaluatorStates.VERY_LONG, portfolio)
    def test_check_and_adapt_order_details_if_necessary(self):
        atmc = AbstractTradingModeCreator(None)

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 1,
                    Ecmsc.LIMITS_COST_MAX.value: 200
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        # correct min
        quantity = 0.5
        price = 2
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct max
        quantity = 100
        price = 2
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct
        quantity = 10
        price = 0.6
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct
        quantity = 3
        price = 49.9
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # invalid price >
        quantity = 1
        price = 100
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        # invalid price <
        quantity = 1
        price = 0.1
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        # invalid cost <
        quantity = 0.5
        price = 1
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        # invalid cost >
        quantity = 10
        price = 49
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(1.83673469, 49),
                                                (4.08163265, 49),
                                                (4.08163265, 49)]

        # invalid cost with invalid price >=
        quantity = 10
        price = 50
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(2, 50), (4, 50), (4, 50)]

        # invalid cost with invalid price >
        quantity = 10
        price = 51
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        # invalid amount >
        quantity = 200
        price = 5
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price,
            symbol_market) == [(40.0, 5), (40.0, 5), (40.0, 5), (40.0, 5),
                               (40.0, 5)]

        # invalid amount <
        quantity = 0.4
        price = 5
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.0000005,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 0.00000001,
                    Ecmsc.LIMITS_COST_MAX.value: 10
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.000005,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        # correct quantity
        # to test _adapt_order_quantity_because_quantity
        quantity = 5000
        price = 0.001
        expected = [(100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001)]
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == expected
    def test_adapt_quantity(self):
        # will use symbol market
        symbol_market = {
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_AMOUNT.value: 4
            }
        }
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.0001) == 0.0001
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.00015) == 0.0001
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.005) == 0.005
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 1) == 1.0000000000000000000000001
        assert AbstractTradingModeCreator._adapt_quantity(symbol_market,
                                                          1) == 1

        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 56.5128597145) == 56.5128
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 1251.0000014576121234854513) == 1251.0000

        # will use default (0)
        symbol_market = {Ecmsc.PRECISION.value: {}}
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.0001) == 0
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.00015) == 0
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 0.005) == 0
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 1) == 1.0000000000000000000000001
        assert AbstractTradingModeCreator._adapt_quantity(symbol_market,
                                                          1) == 1

        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 56.5128597145) == 56
        assert AbstractTradingModeCreator._adapt_quantity(
            symbol_market, 1251.0000014576121234854513) == 1251
    def test_can_create_order_unknown_symbols(self):
        config, exchange, trader, symbol = self._get_tools()
        portfolio = trader.get_portfolio()
        unknown_symbol = "VI?/BTC"
        unknown_market = "BTC/*s?"
        unknown_everything = "VI?/*s?"

        # buy order with unknown market
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_market, exchange, EvaluatorStates.LONG, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_market, exchange, EvaluatorStates.VERY_LONG, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            unknown_market, exchange, EvaluatorStates.SHORT, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            unknown_market, exchange, EvaluatorStates.VERY_SHORT, portfolio)

        # sell order with unknown symbol
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_symbol, exchange, EvaluatorStates.SHORT, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_symbol, exchange, EvaluatorStates.VERY_SHORT, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            unknown_symbol, exchange, EvaluatorStates.LONG, portfolio)
        assert AbstractTradingModeCreator(None).can_create_order(
            unknown_symbol, exchange, EvaluatorStates.VERY_LONG, portfolio)

        # neutral state with unknown symbol, market and everything
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_symbol, exchange, EvaluatorStates.NEUTRAL, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_market, exchange, EvaluatorStates.NEUTRAL, portfolio)
        assert not AbstractTradingModeCreator(None).can_create_order(
            unknown_everything, exchange, EvaluatorStates.NEUTRAL, portfolio)
    def test_adapt_price(self):
        # will use symbol market
        symbol_market = {
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 4
            }
        }
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.0001) == 0.0001
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.00015) == 0.0001
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.005) == 0.005
        assert AbstractTradingModeCreator.adapt_price(symbol_market, 1) == 1

        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      56.5128597145) == 56.5128
        assert AbstractTradingModeCreator.adapt_price(
            symbol_market, 1251.0000014576121234854513) == 1251.0000

        # will use default (CURRENCY_DEFAULT_MAX_PRICE_DIGITS)
        symbol_market = {Ecmsc.PRECISION.value: {}}
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.0001) == 0.0001
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.00015) == 0.00014999
        assert AbstractTradingModeCreator.adapt_price(symbol_market,
                                                      0.005) == 0.005
        assert AbstractTradingModeCreator.adapt_price(
            symbol_market, 1) == 1.0000000000000000000000001
        assert AbstractTradingModeCreator.adapt_price(symbol_market, 1) == 1

        assert AbstractTradingModeCreator.adapt_price(
            symbol_market, 56.5128597145) == 56.51285971
        assert AbstractTradingModeCreator.adapt_price(
            symbol_market, 1251.0000014576121234854513) == 1251.00000145
Ejemplo n.º 6
0
 async def test_get_value_or_default(self):
     test_dict = {"a": 1, "b": 2, "c": 3}
     assert AbstractTradingModeCreator.get_value_or_default(test_dict, "b", default="") == 2
     assert AbstractTradingModeCreator.get_value_or_default(test_dict, "d") is math.nan
     assert AbstractTradingModeCreator.get_value_or_default(test_dict, "d", default="") == ""
Ejemplo n.º 7
0
    async def test_get_additional_dusts_to_quantity_if_necessary(self):
        symbol_market = {Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 1
            }
        }}

        current_symbol_holding = 5
        quantity = 4
        price = 1
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == quantity + 0

        current_symbol_holding = 5
        quantity = 4.5
        price = 1
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == quantity + 0.5

        symbol_market = {Ecmsc.LIMITS.value: {
            Ecmsc.LIMITS_AMOUNT.value: {
                Ecmsc.LIMITS_AMOUNT_MIN.value: 0.005
            },
            Ecmsc.LIMITS_COST.value: {
                Ecmsc.LIMITS_COST_MIN.value: 0.00005
            }
        }}

        current_symbol_holding = 0.99000000001
        quantity = 0.9
        price = 0.5
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == quantity + 0

        current_symbol_holding = 0.99000000001
        quantity = 0.0215245845
        price = 0.5
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == quantity + 0

        current_symbol_holding = 0.99999999
        quantity = 0.99999
        price = 0.5
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == 0.99999999

        current_symbol_holding = 0.88
        quantity = 0.7055680057024826
        price = 0.0002
        assert AbstractTradingModeCreator.add_dusts_to_quantity_if_necessary(quantity,
                                                                             price,
                                                                             symbol_market,
                                                                             current_symbol_holding) == 0.88
    async def test_get_min_max_amounts():
        # normal values
        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: None,
                    Ecmsc.LIMITS_COST_MAX.value: None
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            }
        }
        min_quantity, max_quantity, min_cost, max_cost, min_price, max_price = \
            AbstractTradingModeCreator.get_min_max_amounts(symbol_market)
        assert min_quantity == 0.5
        assert max_quantity == 100
        assert min_cost is None
        assert max_cost is None
        assert min_price == 0.5
        assert max_price == 50

        # missing all values
        min_quantity, max_quantity, min_cost, max_cost, min_price, max_price = \
            AbstractTradingModeCreator.get_min_max_amounts({})
        assert min_quantity is None
        assert max_quantity is None
        assert min_cost is None
        assert max_cost is None
        assert min_price is None
        assert max_price is None

        # missing all values: asign default
        min_quantity, max_quantity, min_cost, max_cost, min_price, max_price = \
            AbstractTradingModeCreator.get_min_max_amounts({}, "xyz")
        assert min_quantity == "xyz"
        assert max_quantity == "xyz"
        assert min_cost == "xyz"
        assert max_cost == "xyz"
        assert min_price == "xyz"
        assert max_price == "xyz"

        # missing values: assign default

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: None,
                    Ecmsc.LIMITS_COST_MAX.value: None
                }
            }
        }
        min_quantity, max_quantity, min_cost, max_cost, min_price, max_price = \
            AbstractTradingModeCreator.get_min_max_amounts(symbol_market, "xyz")
        assert min_quantity == 0.5
        assert max_quantity == 100
        assert min_cost == "xyz"  # None is not a valid value => assign default
        assert max_cost == "xyz"  # None is not a valid value => assign default
        assert min_price == "xyz"
        assert max_price == "xyz"
    async def test_split_orders(self):
        atmc = AbstractTradingModeCreator(None)

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 1,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 1,
                    Ecmsc.LIMITS_COST_MAX.value: 30
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.001,
                    Ecmsc.LIMITS_PRICE_MAX.value: 1000
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 1,
                Ecmsc.PRECISION_AMOUNT.value: 1
            }
        }

        symbol_market_without_max = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 1,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: None,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 1,
                    Ecmsc.LIMITS_COST_MAX.value: None
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 1,
                    Ecmsc.LIMITS_PRICE_MAX.value: None
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 1,
                Ecmsc.PRECISION_AMOUNT.value: 1
            }
        }
        max_cost = symbol_market[Ecmsc.LIMITS.value][Ecmsc.LIMITS_COST.value][
            Ecmsc.LIMITS_COST_MAX.value]
        max_quantity = symbol_market[Ecmsc.LIMITS.value][
            Ecmsc.LIMITS_AMOUNT.value][Ecmsc.LIMITS_AMOUNT_MAX.value]

        # normal situation, split because of cost
        total_price = 100
        valid_quantity = 5
        price = 20
        assert atmc._split_orders(total_price, max_cost, valid_quantity,
                                  max_quantity, price, valid_quantity, symbol_market) \
            == [(0.5, 20), (1.5, 20), (1.5, 20), (1.5, 20)]

        # normal situation, split because of quantity
        total_price = 5.0255
        valid_quantity = 502.55
        price = 0.01
        assert atmc._split_orders(total_price, max_cost, valid_quantity,
                                  max_quantity, price, valid_quantity, symbol_market) \
            == [(2.5, 0.01), (100, 0.01), (100, 0.01), (100, 0.01), (100, 0.01), (100, 0.01)]

        # missing info situation, split because of cost
        max_quantity = None
        total_price = 100
        valid_quantity = 5
        price = 20
        assert atmc._split_orders(total_price, max_cost, valid_quantity,
                                  max_quantity, price, valid_quantity, symbol_market_without_max) \
            == [(0.5, 20), (1.5, 20), (1.5, 20), (1.5, 20)]

        # missing info situation, split because of quantity
        max_quantity = symbol_market[Ecmsc.LIMITS.value][
            Ecmsc.LIMITS_AMOUNT.value][Ecmsc.LIMITS_AMOUNT_MAX.value]
        max_cost = None
        total_price = 5.0255
        valid_quantity = 502.55
        price = 0.01
        assert atmc._split_orders(total_price, max_cost, valid_quantity,
                                  max_quantity, price, valid_quantity, symbol_market_without_max) \
            == [(2.5, 0.01), (100, 0.01), (100, 0.01), (100, 0.01), (100, 0.01), (100, 0.01)]

        # missing info situation, can't split
        max_quantity = None
        max_cost = None
        total_price = 5.0255
        valid_quantity = 502.55
        price = 0.01
        with pytest.raises(RuntimeError):
            assert atmc._split_orders(total_price, max_cost, valid_quantity,
                                      max_quantity, price, valid_quantity,
                                      symbol_market_without_max)
    async def test_check_and_adapt_order_details_if_necessary(self):
        atmc = AbstractTradingModeCreator(None)

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 1,
                    Ecmsc.LIMITS_COST_MAX.value: 200
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        invalid_cost_symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.5,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: None,
                    Ecmsc.LIMITS_COST_MAX.value: None
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.5,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        # correct min
        quantity = 0.5
        price = 2
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct max
        quantity = 100
        price = 2
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct
        quantity = 10
        price = 0.6
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # correct
        quantity = 3
        price = 49.9
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # invalid price > but valid cost
        quantity = 1
        price = 100
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # invalid price < but valid cost
        quantity = 10
        price = 0.1
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(quantity, price)]

        # invalid price > and invalid cost from exchange => use price => invalid
        quantity = 1
        price = 100
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, invalid_cost_symbol_market) == []

        # invalid price < and invalid cost from exchange => use price => invalid
        quantity = 1
        price = 0.1
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, invalid_cost_symbol_market) == []

        # invalid cost <
        quantity = 0.5
        price = 1
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        # invalid cost >
        quantity = 10
        price = 49
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(1.83673469, 49),
                                                (4.08163265, 49),
                                                (4.08163265, 49)]

        # high cost but no max cost => valid
        quantity = 10
        price = 49
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(1.83673469, 49),
                                                (4.08163265, 49),
                                                (4.08163265, 49)]

        # invalid cost with invalid price >=
        quantity = 10
        price = 50
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == [(2, 50), (4, 50), (4, 50)]

        # invalid cost with invalid price > and invalid cost from exchange => use price => invalid
        quantity = 10
        price = 51
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, invalid_cost_symbol_market) == []

        # invalid amount >
        quantity = 200
        price = 5
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price,
            symbol_market) == [(40.0, 5), (40.0, 5), (40.0, 5), (40.0, 5),
                               (40.0, 5)]

        # invalid amount <
        quantity = 0.4
        price = 5
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == []

        symbol_market = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.0000005,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: 100,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 0.00000001,
                    Ecmsc.LIMITS_COST_MAX.value: 10
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.000005,
                    Ecmsc.LIMITS_PRICE_MAX.value: 50
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        # correct quantity
        # to test _adapt_order_quantity_because_quantity
        quantity = 5000
        price = 0.001
        expected = [(100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001), (100.0, 0.001),
                    (100.0, 0.001), (100.0, 0.001)]
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market) == expected

        symbol_market_without_max = {
            Ecmsc.LIMITS.value: {
                Ecmsc.LIMITS_AMOUNT.value: {
                    Ecmsc.LIMITS_AMOUNT_MIN.value: 0.0000005,
                    Ecmsc.LIMITS_AMOUNT_MAX.value: None,
                },
                Ecmsc.LIMITS_COST.value: {
                    Ecmsc.LIMITS_COST_MIN.value: 0.00000001,
                    Ecmsc.LIMITS_COST_MAX.value: None
                },
                Ecmsc.LIMITS_PRICE.value: {
                    Ecmsc.LIMITS_PRICE_MIN.value: 0.000005,
                    Ecmsc.LIMITS_PRICE_MAX.value: None
                },
            },
            Ecmsc.PRECISION.value: {
                Ecmsc.PRECISION_PRICE.value: 8,
                Ecmsc.PRECISION_AMOUNT.value: 8
            }
        }

        # high cost but no max cost => no split
        quantity = 10
        price = 49
        assert atmc.check_and_adapt_order_details_if_necessary(
            quantity, price, symbol_market_without_max) == [(10, 49)]

        # high quantity but no max quantity => no split
        quantity = 10000000
        price = 49
        assert atmc.check_and_adapt_order_details_if_necessary(quantity, price, symbol_market_without_max) == \
            [(10000000, 49)]

        # high price but no max price => no split
        quantity = 10
        price = 4900000
        assert atmc.check_and_adapt_order_details_if_necessary(quantity, price, symbol_market_without_max) == \
            [(10, 4900000)]