Ejemplo n.º 1
0
def test_buy_long(trader: Trader):
    """
    Test trader buy long functionality.
    :param trader: Trader object.
    """
    trader.currentPeriod = {'date_utc': 'test_date'}
    trader.currentPrice = 10

    transaction_fee = trader.startingBalance * trader.transactionFeePercentageDecimal
    coin = (trader.startingBalance - transaction_fee) / trader.currentPrice

    trader.buy_long("test_buy", smartEnter=True)
    assert trader.smartStopLossEnter is True
    assert trader.stopLossExit is False
    assert trader.currentPosition == LONG
    assert trader.buyLongPrice == trader.currentPrice
    assert trader.longTrailingPrice == trader.currentPrice
    assert trader.balance == 0
    assert trader.coin == coin
    assert trader.commissionsPaid == transaction_fee
    assert trader.trades[-1] == {
        'date': 'test_date',
        'action': 'test_buy',
        'net': round(trader.get_net(), trader.precision)
    }
Ejemplo n.º 2
0
 def setUp(self) -> None:
     """
     Sets up a backtester object.
     """
     self.trader = Trader(symbol="BTCUSDT",
                          precision=2,
                          startingBalance=1000)
Ejemplo n.º 3
0
def test_sell_short(trader: Trader):
    """
    Test trader sell short functionality.
    :param trader: Trader object.
    """
    trader.currentPeriod = {'date_utc': 'test_date'}
    trader.currentPrice = 10

    transaction_fee = trader.startingBalance * trader.transactionFeePercentageDecimal
    coin_owed = trader.startingBalance / trader.currentPrice

    trader.sell_short("test_short")
    assert trader.smartStopLossEnter is False
    assert trader.stopLossExit is False
    assert trader.balance == trader.startingBalance * 2 - transaction_fee
    assert trader.currentPosition == SHORT
    assert trader.sellShortPrice == trader.currentPrice
    assert trader.shortTrailingPrice == trader.currentPrice
    assert trader.coin == 0
    assert trader.coinOwed == coin_owed
    assert trader.commissionsPaid == transaction_fee
    assert trader.trades[-1] == {
        'date': 'test_date',
        'action': 'test_short',
        'net': round(trader.get_net(), trader.precision)
    }
Ejemplo n.º 4
0
def test_get_safe_rounded_string(trader: Trader):
    """
    Test trader get safe rounded string functionality.
    """
    trader.precision = 3
    assert trader.get_safe_rounded_string(value=5.1231) == '$5.123'
    assert trader.get_safe_rounded_string(value=5.12345, roundDigits=5) == '$5.12345'
    assert trader.get_safe_rounded_string(value=5.12345, roundDigits=0) == '$5.0'
    assert trader.get_safe_rounded_string(1.23, roundDigits=2, symbol='*', direction='right', multiplier=5) == '6.15*'
Ejemplo n.º 5
0
def test_set_and_reset_smart_stop_loss(trader: Trader):
    """
    Test trader set and reset smart stop loss functionality.
    :param trader: Trader object.
    """
    trader.set_smart_stop_loss_counter(5)
    trader.smartStopLossCounter = 0
    trader.reset_smart_stop_loss()
    assert trader.smartStopLossCounter == 5
Ejemplo n.º 6
0
def test_set_safety_timer(trader: Trader):
    """
    Test trader set safety timer functionality.
    :param trader: Trader object.
    """
    trader.set_safety_timer(0)
    assert trader.safetyTimer is None

    trader.set_safety_timer(10)
    assert trader.safetyTimer == 10
Ejemplo n.º 7
0
def test_apply_take_profit_settings(trader: Trader):
    """
    Test trader apply take profit settings functionality.
    :param trader: Trader object.
    """
    take_profit_settings = {
        'takeProfitPercentage': 25,
        'takeProfitType': STOP
    }
    trader.apply_take_profit_settings(take_profit_settings)

    assert trader.takeProfitPercentageDecimal == 0.25
    assert trader.takeProfitType == STOP
Ejemplo n.º 8
0
def test_buy_short(trader: Trader):
    """
    Test trader buy short functionality.
    :param trader: Trader object.
    """
    trader.currentPeriod = {'date_utc': 'test_date'}
    trader.currentPrice = 10

    transaction_fee = trader.startingBalance * trader.transactionFeePercentageDecimal
    coin_owed = trader.startingBalance / trader.currentPrice

    trader.sell_short("test_short", smartEnter=True)
    trader.currentPrice = 5

    previous_transaction_fee = transaction_fee
    transaction_fee = coin_owed * trader.currentPrice * trader.transactionFeePercentageDecimal
    balance = trader.balance - coin_owed * trader.currentPrice - transaction_fee

    trader.buy_short("test_end_short", stopLossExit=True)
    assert trader.stopLossExit is True
    assert trader.smartStopLossEnter is False
    assert trader.currentPosition is None
    assert trader.previousPosition == SHORT
    assert trader.sellShortPrice is None
    assert trader.shortTrailingPrice is None
    assert trader.balance == balance
    assert trader.commissionsPaid == previous_transaction_fee + transaction_fee
    assert trader.coin == 0
    assert trader.coinOwed == 0
    assert trader.trades[-1] == {
        'date': 'test_date',
        'action': 'test_end_short',
        'net': round(trader.get_net(), trader.precision)
    }
Ejemplo n.º 9
0
def test_get_trend(trader: Trader):
    """
    Test trader get trend functionality.
    :param trader: Trader object.
    """
    assert trader.get_trend() is None

    bullish_strategy1 = Strategy(name='b1', parent=None)
    bullish_strategy1.trend = BULLISH

    trader.strategies['b1'] = bullish_strategy1
    assert trader.get_trend() == BULLISH

    bullish_strategy2 = Strategy(name='b2', parent=None)
    bullish_strategy2.trend = BULLISH

    trader.strategies['b2'] = bullish_strategy2
    assert trader.get_trend() == BULLISH

    bearish_strategy = Strategy(name='b3', parent=None)
    bearish_strategy.trend = BEARISH

    trader.strategies['b3'] = bearish_strategy
    assert trader.get_trend() is None

    for strategy in trader.strategies.values():
        strategy.trend = BEARISH

    assert trader.get_trend() == BEARISH
Ejemplo n.º 10
0
def test_get_strategy_inputs(trader: Trader):
    """
    Test trader get strategy inputs functionality.
    :param trader: Trader object.
    """
    dummy_strategy = Strategy(name="dummy", parent=None)

    def temp():
        return 3, 4, 5

    dummy_strategy.get_params = temp
    assert dummy_strategy.get_params() == (3, 4, 5)

    trader.strategies = {'dummy': dummy_strategy}
    assert trader.get_strategy_inputs('dummy') == '3, 4, 5'
Ejemplo n.º 11
0
def test_add_trade(trader: Trader):
    """
    Test trader add trade functionality.
    :param trader: Trader object.
    """
    trader.currentPeriod = {'date_utc': 'test_date'}
    trader.currentPrice = 10

    trader.add_trade(message="test_trade", stopLossExit=True, smartEnter=True)
    assert trader.stopLossExit is True
    assert trader.smartStopLossEnter is True
    assert trader.trades[-1] == {
        'date': 'test_date',
        'action': 'test_trade',
        'net': trader.startingBalance
    }
Ejemplo n.º 12
0
def test_apply_loss_settings(trader: Trader):
    """
    Test trader apply loss settings functionality.
    :param trader: Trader object.
    """
    loss_settings = {
        'lossType': STOP,
        'lossPercentage': 5.5,
        'smartStopLossCounter': 15,
        'safetyTimer': 45
    }
    trader.apply_loss_settings(loss_settings)

    assert trader.lossStrategy == STOP
    assert trader.lossPercentageDecimal == 0.055
    assert trader.smartStopLossInitialCounter == 15
    assert trader.smartStopLossCounter == 15
    assert trader.safetyTimer == 45
Ejemplo n.º 13
0
def test_get_strategies_info_string(trader: Trader):
    """
    Test trader get strategies info string functionality.
    :param trader: Trader object.
    """
    dummy_strategy = Strategy(name="dummy", parent=None)
    dummy_strategy2 = Strategy(name='dummy2', parent=None)

    def temp():
        return 3, 4, 5

    def temp2():
        return 5, 6, 7, 8, 9, 10

    dummy_strategy.get_params = temp
    dummy_strategy2.get_params = temp2
    expected_string = 'Strategies:\n\tDummy: 3, 4, 5\n\tDummy2: 5, 6, 7, 8, 9, 10'

    trader.strategies = {'dummy': dummy_strategy, 'dummy2': dummy_strategy2}
    assert trader.get_strategies_info_string() == expected_string
Ejemplo n.º 14
0
def test_get_stop_loss_strategy_string(trader: Trader):
    """
    Test trader sell long functionality.
    :param trader: Trader object.
    """
    trader.lossStrategy = STOP
    assert trader.get_stop_loss_strategy_string() == "Stop Loss"

    trader.lossStrategy = TRAILING
    assert trader.get_stop_loss_strategy_string() == "Trailing Loss"

    trader.lossStrategy = None
    assert trader.get_stop_loss_strategy_string() == "None"
Ejemplo n.º 15
0
class TestBaseTrader(unittest.TestCase):
    def setUp(self) -> None:
        """
        Sets up a backtester object.
        """
        self.trader = Trader(symbol="BTCUSDT",
                             precision=2,
                             startingBalance=1000)

    def test_add_trade(self):
        with pytest.raises(
                NotImplementedError,
                match='Please implement a function for adding trades.'):
            self.trader.add_trade()

    def test_buy_long(self):
        with pytest.raises(
                NotImplementedError,
                match='Please implement a function for buying long.'):
            self.trader.buy_long()

    def test_sell_long(self):
        with pytest.raises(
                NotImplementedError,
                match='Please implement a function for selling long.'):
            self.trader.sell_long()

    def test_sell_short(self):
        with pytest.raises(
                NotImplementedError,
                match='Please implement a function for selling short.'):
            self.trader.sell_short()

    def test_buy_short(self):
        with pytest.raises(
                NotImplementedError,
                match='Please implement a function for buying short.'):
            self.trader.buy_short()

    def test_set_and_reset_smart_stop_loss(self):
        self.trader.set_smart_stop_loss_counter(5)
        self.trader.smartStopLossCounter = 0
        self.trader.reset_smart_stop_loss()
        self.assertEqual(self.trader.smartStopLossCounter, 5)

    def test_set_safety_timer(self):
        self.trader.set_safety_timer(0)
        self.assertEqual(self.trader.safetyTimer, None)

        self.trader.set_safety_timer(10)
        self.assertEqual(self.trader.safetyTimer, 10)

    def test_apply_take_profit_settings(self):
        take_profit_settings = {
            'takeProfitPercentage': 25,
            'takeProfitType': STOP
        }
        self.trader.apply_take_profit_settings(take_profit_settings)

        self.assertEqual(self.trader.takeProfitPercentageDecimal, 0.25)
        self.assertEqual(self.trader.takeProfitType, STOP)

    def test_apply_loss_settings(self):
        loss_settings = {
            'lossType': STOP,
            'lossPercentage': 5.5,
            'smartStopLossCounter': 15,
            'safetyTimer': 45
        }
        self.trader.apply_loss_settings(loss_settings)

        self.assertEqual(self.trader.lossStrategy, STOP)
        self.assertEqual(self.trader.lossPercentageDecimal, 0.055)
        self.assertEqual(self.trader.smartStopLossInitialCounter, 15)
        self.assertEqual(self.trader.smartStopLossCounter, 15)
        self.assertEqual(self.trader.safetyTimer, 45)

    def test_setup_strategies(self):
        pass

    def test_get_stop_loss(self):
        self.trader.lossStrategy = STOP
        self.trader.lossPercentageDecimal = 0.1
        self.trader.currentPrice = 5

        self.trader.currentPosition = LONG
        self.trader.buyLongPrice = 10
        self.assertEqual(self.trader.get_stop_loss(),
                         10 * (1 - self.trader.lossPercentageDecimal))

        self.trader.currentPosition = SHORT
        self.trader.sellShortPrice = 10
        self.assertEqual(self.trader.get_stop_loss(),
                         10 * (1 + self.trader.lossPercentageDecimal))

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_stop_loss(), None)

        # TODO implement trailing stop loss test

    def test_get_stop_loss_strategy_string(self):
        self.trader.lossStrategy = STOP
        self.assertEqual(self.trader.get_stop_loss_strategy_string(),
                         "Stop Loss")

        self.trader.lossStrategy = TRAILING
        self.assertEqual(self.trader.get_stop_loss_strategy_string(),
                         "Trailing Loss")

        self.trader.lossStrategy = None
        self.assertEqual(self.trader.get_stop_loss_strategy_string(), "None")

    def test_get_strategy_inputs(self):
        pass

    def test_get_strategies_info_string(self):
        pass

    def test_get_cumulative_trend(self):
        trends = [BEARISH, BULLISH, BEARISH, None]
        self.assertEqual(self.trader.get_cumulative_trend(trends), None)

        trends = [BEARISH, BEARISH, BEARISH]
        self.assertEqual(self.trader.get_cumulative_trend(trends), BEARISH)

        trends = [BULLISH, BULLISH, BULLISH, BULLISH, BULLISH]
        self.assertEqual(self.trader.get_cumulative_trend(trends), BULLISH)

    def test_get_profit_percentage(self):
        self.assertEqual(self.trader.get_profit_percentage(100, 200), 100)
        self.assertEqual(self.trader.get_profit_percentage(100, 0), -100)
        self.assertEqual(self.trader.get_profit_percentage(100, 50), -50)
        self.assertEqual(self.trader.get_profit_percentage(100, 130), 30)

    def test_get_trailing_or_stop_loss_string(self):
        self.assertEqual(self.trader.get_trailing_or_stop_type_string(STOP),
                         'Stop')
        self.assertEqual(
            self.trader.get_trailing_or_stop_type_string(TRAILING), 'Trailing')
        self.assertEqual(self.trader.get_trailing_or_stop_type_string(None),
                         'None')

    def test_get_trend_string(self):
        self.assertEqual(self.trader.get_trend_string(None), str(None))
        self.assertEqual(self.trader.get_trend_string(BEARISH), "Bearish")
        self.assertEqual(self.trader.get_trend_string(BULLISH), "Bullish")

    def test_get_profit_or_loss_string(self):
        self.assertEqual(self.trader.get_profit_or_loss_string(0), 'Profit')
        self.assertEqual(self.trader.get_profit_or_loss_string(5), 'Profit')
        self.assertEqual(self.trader.get_profit_or_loss_string(-1), 'Loss')

    def test_get_position_string(self):
        self.trader.currentPosition = LONG
        self.assertEqual(self.trader.get_position_string(), "Long")

        self.trader.currentPosition = SHORT
        self.assertEqual(self.trader.get_position_string(), "Short")

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_position_string(), "None")

    def test_get_position(self):
        self.trader.currentPosition = LONG
        self.assertEqual(self.trader.get_position(), LONG)

        self.trader.currentPosition = SHORT
        self.assertEqual(self.trader.get_position(), SHORT)

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_position(), None)

    def test_get_safe_rounded_percentage(self):
        self.assertEqual(self.trader.get_safe_rounded_percentage(0.05123),
                         '5.12%')
        self.assertEqual(self.trader.get_safe_rounded_percentage(0.01), '1.0%')

    def test_get_safe_rounded_string(self):
        self.trader.precision = 3
        self.assertEqual(self.trader.get_safe_rounded_string(value=5.1231),
                         '$5.123')
        self.assertEqual(
            self.trader.get_safe_rounded_string(value=5.12345, roundDigits=5),
            '$5.12345')
        self.assertEqual(
            self.trader.get_safe_rounded_string(value=5.12345, roundDigits=0),
            '$5.0')
        self.assertEqual(
            self.trader.get_safe_rounded_string(value=1.23,
                                                roundDigits=2,
                                                symbol='*',
                                                direction='right',
                                                multiplier=5), '6.15*')

    def test_get_take_profit(self):
        self.trader.takeProfitType = STOP
        self.trader.takeProfitPercentageDecimal = 0.05

        self.trader.currentPosition = LONG
        self.trader.buyLongPrice = 10
        self.assertEqual(self.trader.get_take_profit(), 10 * (1 + 0.05))

        self.trader.currentPosition = SHORT
        self.trader.sellShortPrice = 10
        self.assertEqual(self.trader.get_take_profit(), 10 * (1 - 0.05))

        self.trader.takeProfitType = None
        self.assertEqual(self.trader.get_take_profit(), None)

        self.trader.takeProfitType = 5
        with pytest.raises(ValueError,
                           match="Invalid type of take profit type provided."):
            self.trader.get_take_profit()

    def test_get_net(self):
        pass

    def test_get_trend(self):
        pass
Ejemplo n.º 16
0
def test_get_net(trader: Trader):
    """
    Test trader get net.
    """
    trader.currentPeriod = {'date_utc': 'test_date'}
    trader.currentPrice = 100
    trader.buy_long("test")

    trader.currentPrice = 200
    assert trader.get_net() == trader.currentPrice * trader.coin

    trader.currentPrice = 50
    assert trader.get_net() == trader.currentPrice * trader.coin
    trader.sell_long("end_buy_net")

    trader.startingBalance = trader.balance = 1000
    trader.commissionsPaid = 0
    trader.currentPrice = 20
    trader.sell_short("test_short")
    assert trader.get_net() == trader.startingBalance - trader.commissionsPaid

    trader.currentPrice = 10
    trader.buy_short("test_end_short")
    assert round(trader.get_net(), 2) == 1498.50

    trader.startingBalance = trader.balance = 1000
    trader.commissionsPaid = 0
    trader.currentPrice = 5
    trader.sell_short("test")
    trader.buy_short("test")
    assert trader.get_net() == 998
Ejemplo n.º 17
0
def test_get_take_profit(trader: Trader):
    """
    Test trader get take profit functionality.
    """
    trader.takeProfitType = STOP
    trader.takeProfitPercentageDecimal = 0.05

    trader.currentPosition = LONG
    trader.buyLongPrice = 10
    assert trader.get_take_profit() == 10 * (1 + 0.05)

    trader.currentPosition = SHORT
    trader.sellShortPrice = 10
    assert trader.get_take_profit() == 10 * (1 - 0.05)

    trader.takeProfitType = None
    assert trader.get_take_profit() is None

    trader.takeProfitType = 5
    with pytest.raises(ValueError, match="Invalid type of take profit type provided."):
        trader.get_take_profit()
Ejemplo n.º 18
0
def test_get_safe_rounded_percentage(trader: Trader, percentage, expected):
    """
    Test trader get safe rounded percentage functionality.
    """
    assert trader.get_safe_rounded_percentage(percentage) == expected
Ejemplo n.º 19
0
def test_get_position(trader: Trader, current_position):
    """
    Test trader get position functionality.
    """
    trader.currentPosition = current_position
    assert trader.get_position() == current_position
Ejemplo n.º 20
0
def test_get_position_string(trader: Trader, current_position, expected):
    """
    Test trader get position string functionality.
    """
    trader.currentPosition = current_position
    assert trader.get_position_string() == expected
Ejemplo n.º 21
0
def test_get_profit_or_loss_string(trader: Trader, profit_or_loss, expected):
    """
    Test trader get profit or loss string functionality.
    """
    assert trader.get_profit_or_loss_string(profit_or_loss) == expected
Ejemplo n.º 22
0
def test_get_profit_percentage(trader: Trader, initial_net, final_net, expected):
    """
    Test trader get profit percentage.
    """
    assert trader.get_profit_percentage(initial_net, final_net) == expected
Ejemplo n.º 23
0
def get_trader_object() -> Trader:
    """
    Get a trader object.
    :return: Trader
    """
    return Trader(symbol="BTCUSDT", precision=2, startingBalance=1000)
Ejemplo n.º 24
0
def test_get_stop_loss(trader: Trader):
    """
    Test trader get stop loss functionality.
    :param trader: Trader object.
    """
    trader.lossStrategy = STOP
    trader.lossPercentageDecimal = 0.1
    trader.currentPrice = 5

    trader.currentPosition = LONG
    trader.buyLongPrice = 10
    assert trader.get_stop_loss() == 10 * (1 - trader.lossPercentageDecimal)

    trader.currentPosition = SHORT
    trader.sellShortPrice = 10
    assert trader.get_stop_loss() == 10 * (1 + trader.lossPercentageDecimal)

    trader.currentPosition = None
    assert trader.get_stop_loss() is None
Ejemplo n.º 25
0
class TestBaseTrader(unittest.TestCase):
    def setUp(self) -> None:
        """
        Sets up a backtester object.
        """
        self.trader = Trader(symbol="BTCUSDT", precision=2, startingBalance=1000)

    def test_add_trade(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 10

        self.trader.add_trade(message="test_trade", stopLossExit=True, smartEnter=True)
        self.assertEqual(self.trader.stopLossExit, True)
        self.assertEqual(self.trader.smartStopLossEnter, True)
        self.assertEqual(self.trader.trades[-1], {
            'date': 'test_date',
            'action': 'test_trade',
            'net': self.trader.startingBalance
        })

    def test_buy_long(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 10

        transaction_fee = self.trader.startingBalance * self.trader.transactionFeePercentageDecimal
        coin = (self.trader.startingBalance - transaction_fee) / self.trader.currentPrice

        self.trader.buy_long("test_buy", smartEnter=True)
        self.assertEqual(self.trader.smartStopLossEnter, True)
        self.assertEqual(self.trader.stopLossExit, False)
        self.assertEqual(self.trader.currentPosition, LONG)
        self.assertEqual(self.trader.buyLongPrice, self.trader.currentPrice)
        self.assertEqual(self.trader.longTrailingPrice, self.trader.currentPrice)
        self.assertEqual(self.trader.balance, 0)
        self.assertEqual(self.trader.coin, coin)
        self.assertEqual(self.trader.commissionsPaid, transaction_fee)
        self.assertEqual(self.trader.trades[-1], {
            'date': 'test_date',
            'action': 'test_buy',
            'net': round(self.trader.get_net(), self.trader.precision)
        })

    def test_sell_long(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 10

        transaction_fee = self.trader.startingBalance * self.trader.transactionFeePercentageDecimal
        coin = (self.trader.startingBalance - transaction_fee) / self.trader.currentPrice

        self.trader.buy_long("test_buy")
        self.trader.currentPrice = 15

        previous_transaction_fee = transaction_fee
        transaction_fee = coin * self.trader.currentPrice * self.trader.transactionFeePercentageDecimal
        balance = coin * self.trader.currentPrice - transaction_fee

        self.trader.sell_long("test_sell", stopLossExit=True)
        self.assertEqual(self.trader.smartStopLossEnter, False)
        self.assertEqual(self.trader.stopLossExit, True)
        self.assertEqual(self.trader.balance, balance)
        self.assertEqual(self.trader.currentPosition, None)
        self.assertEqual(self.trader.previousPosition, LONG)
        self.assertEqual(self.trader.buyLongPrice, None)
        self.assertEqual(self.trader.longTrailingPrice, None)
        self.assertEqual(self.trader.commissionsPaid, transaction_fee + previous_transaction_fee)
        self.assertEqual(self.trader.coin, 0)
        self.assertEqual(self.trader.trades[-1], {
            'date': 'test_date',
            'action': 'test_sell',
            'net': round(self.trader.get_net(), self.trader.precision)
        })

    def test_sell_short(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 10

        transaction_fee = self.trader.startingBalance * self.trader.transactionFeePercentageDecimal
        coin_owed = self.trader.startingBalance / self.trader.currentPrice

        self.trader.sell_short("test_short")
        self.assertEqual(self.trader.smartStopLossEnter, False)
        self.assertEqual(self.trader.stopLossExit, False)
        self.assertEqual(self.trader.balance, self.trader.startingBalance * 2 - transaction_fee)
        self.assertEqual(self.trader.currentPosition, SHORT)
        self.assertEqual(self.trader.sellShortPrice, self.trader.currentPrice)
        self.assertEqual(self.trader.shortTrailingPrice, self.trader.currentPrice)
        self.assertEqual(self.trader.coin, 0)
        self.assertEqual(self.trader.coinOwed, coin_owed)
        self.assertEqual(self.trader.commissionsPaid, transaction_fee)
        self.assertEqual(self.trader.trades[-1], {
            'date': 'test_date',
            'action': 'test_short',
            'net': round(self.trader.get_net(), self.trader.precision)
        })

    def test_buy_short(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 10

        transaction_fee = self.trader.startingBalance * self.trader.transactionFeePercentageDecimal
        coin_owed = self.trader.startingBalance / self.trader.currentPrice

        self.trader.sell_short("test_short", smartEnter=True)
        self.trader.currentPrice = 5

        previous_transaction_fee = transaction_fee
        transaction_fee = coin_owed * self.trader.currentPrice * self.trader.transactionFeePercentageDecimal
        balance = self.trader.balance - coin_owed * self.trader.currentPrice - transaction_fee

        self.trader.buy_short("test_end_short", stopLossExit=True)
        self.assertEqual(self.trader.stopLossExit, True)
        self.assertEqual(self.trader.smartStopLossEnter, False)
        self.assertEqual(self.trader.currentPosition, None)
        self.assertEqual(self.trader.previousPosition, SHORT)
        self.assertEqual(self.trader.sellShortPrice, None)
        self.assertEqual(self.trader.shortTrailingPrice, None)
        self.assertEqual(self.trader.balance, balance)
        self.assertEqual(self.trader.commissionsPaid, previous_transaction_fee + transaction_fee)
        self.assertEqual(self.trader.coin, 0)
        self.assertEqual(self.trader.coinOwed, 0)
        self.assertEqual(self.trader.trades[-1], {
            'date': 'test_date',
            'action': 'test_end_short',
            'net': round(self.trader.get_net(), self.trader.precision)
        })

    def test_set_and_reset_smart_stop_loss(self):
        self.trader.set_smart_stop_loss_counter(5)
        self.trader.smartStopLossCounter = 0
        self.trader.reset_smart_stop_loss()
        self.assertEqual(self.trader.smartStopLossCounter, 5)

    def test_set_safety_timer(self):
        self.trader.set_safety_timer(0)
        self.assertEqual(self.trader.safetyTimer, None)

        self.trader.set_safety_timer(10)
        self.assertEqual(self.trader.safetyTimer, 10)

    def test_apply_take_profit_settings(self):
        take_profit_settings = {
            'takeProfitPercentage': 25,
            'takeProfitType': STOP
        }
        self.trader.apply_take_profit_settings(take_profit_settings)

        self.assertEqual(self.trader.takeProfitPercentageDecimal, 0.25)
        self.assertEqual(self.trader.takeProfitType, STOP)

    def test_apply_loss_settings(self):
        loss_settings = {
            'lossType': STOP,
            'lossPercentage': 5.5,
            'smartStopLossCounter': 15,
            'safetyTimer': 45
        }
        self.trader.apply_loss_settings(loss_settings)

        self.assertEqual(self.trader.lossStrategy, STOP)
        self.assertEqual(self.trader.lossPercentageDecimal, 0.055)
        self.assertEqual(self.trader.smartStopLossInitialCounter, 15)
        self.assertEqual(self.trader.smartStopLossCounter, 15)
        self.assertEqual(self.trader.safetyTimer, 45)

    def test_get_stop_loss(self):
        self.trader.lossStrategy = STOP
        self.trader.lossPercentageDecimal = 0.1
        self.trader.currentPrice = 5

        self.trader.currentPosition = LONG
        self.trader.buyLongPrice = 10
        self.assertEqual(self.trader.get_stop_loss(), 10 * (1 - self.trader.lossPercentageDecimal))

        self.trader.currentPosition = SHORT
        self.trader.sellShortPrice = 10
        self.assertEqual(self.trader.get_stop_loss(), 10 * (1 + self.trader.lossPercentageDecimal))

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_stop_loss(), None)

        # TODO implement trailing stop loss test

    def test_get_stop_loss_strategy_string(self):
        self.trader.lossStrategy = STOP
        self.assertEqual(self.trader.get_stop_loss_strategy_string(), "Stop Loss")

        self.trader.lossStrategy = TRAILING
        self.assertEqual(self.trader.get_stop_loss_strategy_string(), "Trailing Loss")

        self.trader.lossStrategy = None
        self.assertEqual(self.trader.get_stop_loss_strategy_string(), "None")

    def test_get_strategy_inputs(self):
        dummy_strategy = Strategy(name="dummy", parent=None)

        def temp():
            return 3, 4, 5

        dummy_strategy.get_params = temp
        self.assertEqual(dummy_strategy.get_params(), (3, 4, 5))

        self.trader.strategies = {'dummy': dummy_strategy}
        self.assertEqual(self.trader.get_strategy_inputs('dummy'), '3, 4, 5')

    def test_get_strategies_info_string(self):
        dummy_strategy = Strategy(name="dummy", parent=None)
        dummy_strategy2 = Strategy(name='dummy2', parent=None)

        def temp():
            return 3, 4, 5

        def temp2():
            return 5, 6, 7, 8, 9, 10

        dummy_strategy.get_params = temp
        dummy_strategy2.get_params = temp2
        expected_string = '\nStrategies:\n\tDummy: 3, 4, 5\n\tDummy2: 5, 6, 7, 8, 9, 10'

        self.trader.strategies = {'dummy': dummy_strategy, 'dummy2': dummy_strategy2}
        self.assertEqual(self.trader.get_strategies_info_string(), expected_string)

    def test_get_trend(self):
        self.assertEqual(self.trader.get_trend(), None)

        bullish_strategy1 = Strategy(name='b1', parent=None)
        bullish_strategy1.trend = BULLISH

        self.trader.strategies['b1'] = bullish_strategy1
        self.assertEqual(self.trader.get_trend(), BULLISH)

        bullish_strategy2 = Strategy(name='b2', parent=None)
        bullish_strategy2.trend = BULLISH

        self.trader.strategies['b2'] = bullish_strategy2
        self.assertEqual(self.trader.get_trend(), BULLISH)

        bearish_strategy = Strategy(name='b3', parent=None)
        bearish_strategy.trend = BEARISH

        self.trader.strategies['b3'] = bearish_strategy
        self.assertEqual(self.trader.get_trend(), None)

        for strategy in self.trader.strategies:
            self.trader.strategies[strategy].trend = BEARISH

        self.assertEqual(self.trader.get_trend(), BEARISH)

    def test_setup_strategies(self):
        pass

    def test_get_cumulative_trend(self):
        trends = [BEARISH, BULLISH, BEARISH, None]
        self.assertEqual(self.trader.get_cumulative_trend(trends), None)

        trends = [BEARISH, BEARISH, BEARISH]
        self.assertEqual(self.trader.get_cumulative_trend(trends), BEARISH)

        trends = [BULLISH, BULLISH, BULLISH, BULLISH, BULLISH]
        self.assertEqual(self.trader.get_cumulative_trend(trends), BULLISH)

    def test_get_profit_percentage(self):
        self.assertEqual(self.trader.get_profit_percentage(100, 200), 100)
        self.assertEqual(self.trader.get_profit_percentage(100, 0), -100)
        self.assertEqual(self.trader.get_profit_percentage(100, 50), -50)
        self.assertEqual(self.trader.get_profit_percentage(100, 130), 30)

    def test_get_trailing_or_stop_loss_string(self):
        self.assertEqual(self.trader.get_trailing_or_stop_type_string(STOP), 'Stop')
        self.assertEqual(self.trader.get_trailing_or_stop_type_string(TRAILING), 'Trailing')
        self.assertEqual(self.trader.get_trailing_or_stop_type_string(None), 'None')

    def test_get_trend_string(self):
        self.assertEqual(self.trader.get_trend_string(None), str(None))
        self.assertEqual(self.trader.get_trend_string(BEARISH), "Bearish")
        self.assertEqual(self.trader.get_trend_string(BULLISH), "Bullish")

    def test_get_profit_or_loss_string(self):
        self.assertEqual(self.trader.get_profit_or_loss_string(0), 'Profit')
        self.assertEqual(self.trader.get_profit_or_loss_string(5), 'Profit')
        self.assertEqual(self.trader.get_profit_or_loss_string(-1), 'Loss')

    def test_get_position_string(self):
        self.trader.currentPosition = LONG
        self.assertEqual(self.trader.get_position_string(), "Long")

        self.trader.currentPosition = SHORT
        self.assertEqual(self.trader.get_position_string(), "Short")

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_position_string(), "None")

    def test_get_position(self):
        self.trader.currentPosition = LONG
        self.assertEqual(self.trader.get_position(), LONG)

        self.trader.currentPosition = SHORT
        self.assertEqual(self.trader.get_position(), SHORT)

        self.trader.currentPosition = None
        self.assertEqual(self.trader.get_position(), None)

    def test_get_safe_rounded_percentage(self):
        self.assertEqual(self.trader.get_safe_rounded_percentage(0.05123), '5.12%')
        self.assertEqual(self.trader.get_safe_rounded_percentage(0.01), '1.0%')

    def test_get_safe_rounded_string(self):
        self.trader.precision = 3
        self.assertEqual(self.trader.get_safe_rounded_string(value=5.1231), '$5.123')
        self.assertEqual(self.trader.get_safe_rounded_string(value=5.12345, roundDigits=5), '$5.12345')
        self.assertEqual(self.trader.get_safe_rounded_string(value=5.12345, roundDigits=0), '$5.0')
        self.assertEqual(self.trader.get_safe_rounded_string(value=1.23, roundDigits=2, symbol='*', direction='right',
                                                             multiplier=5), '6.15*')

    def test_get_take_profit(self):
        self.trader.takeProfitType = STOP
        self.trader.takeProfitPercentageDecimal = 0.05

        self.trader.currentPosition = LONG
        self.trader.buyLongPrice = 10
        self.assertEqual(self.trader.get_take_profit(), 10 * (1 + 0.05))

        self.trader.currentPosition = SHORT
        self.trader.sellShortPrice = 10
        self.assertEqual(self.trader.get_take_profit(), 10 * (1 - 0.05))

        self.trader.takeProfitType = None
        self.assertEqual(self.trader.get_take_profit(), None)

        self.trader.takeProfitType = 5
        with pytest.raises(ValueError, match="Invalid type of take profit type provided."):
            self.trader.get_take_profit()

    def test_get_net(self):
        self.trader.currentPeriod = {'date_utc': 'test_date'}
        self.trader.currentPrice = 100
        self.trader.buy_long("test")

        self.trader.currentPrice = 200
        self.assertEqual(self.trader.get_net(), self.trader.currentPrice * self.trader.coin)

        self.trader.currentPrice = 50
        self.assertEqual(self.trader.get_net(), self.trader.currentPrice * self.trader.coin)
        self.trader.sell_long("end_buy_net")

        self.trader.startingBalance = self.trader.balance = 1000
        self.trader.commissionsPaid = 0
        self.trader.currentPrice = 20
        self.trader.sell_short("test_short")
        self.assertEqual(self.trader.get_net(), self.trader.startingBalance - self.trader.commissionsPaid)

        self.trader.currentPrice = 10
        self.trader.buy_short("test_end_short")
        self.assertEqual(round(self.trader.get_net(), 2), 1498.50)

        self.trader.startingBalance = self.trader.balance = 1000
        self.trader.commissionsPaid = 0
        self.trader.currentPrice = 5
        self.trader.sell_short("test")
        self.trader.buy_short("test")
        self.assertEqual(self.trader.get_net(), 998)
Ejemplo n.º 26
0
def test_get_cumulative_trend(trader: Trader, trends, expected):
    """
    Test trader get cumulative trend.
    """
    assert trader.get_cumulative_trend(trends) == expected