Beispiel #1
0
    def test_naive_taxes(
        self,
        closes,
        stop_loss,
        take_profit,
        target_usd_percentage,
        balancing_period,
        distribution,
        balance,
        tax_exemption,
    ):
        distributions = np.stack([distribution, distribution], axis=1)

        stop_loss_index = opt.get_stop_loss_index(closes, stop_loss)
        take_profit_index = opt.get_take_profit_index(closes, take_profit)

        (
            usd_values_without_taxes,
            asset_values_without_taxes,
            _,
        ) = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=balance,
            taxes=False,
        )

        trade_without_taxes = usd_values_without_taxes + asset_values_without_taxes

        usd_values, asset_values, buy_sizes = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=balance,
            taxes=True,
            tax_exemption=tax_exemption,
        )

        assert np.all(usd_values >= 0.0)
        assert np.all(asset_values >= 0.0)
        trade = usd_values + asset_values

        assert np.all(buy_sizes >= 0.0)
        assert np.all(buy_sizes <= 1e-7)

        if not tax_exemption:
            assert np.all(trade <= trade_without_taxes)
Beispiel #2
0
    def test_naive_spread(
        self,
        closes,
        stop_loss,
        take_profit,
        target_usd_percentage,
        balancing_period,
        distribution,
        balance,
    ):
        assume(np.sum(distribution) > 0)
        distributions = np.stack([distribution, distribution], axis=1)

        stop_loss_index = opt.get_stop_loss_index(closes, stop_loss)
        take_profit_index = opt.get_take_profit_index(closes, take_profit)

        (
            usd_values_without_spread,
            asset_values_without_spread,
            _,
        ) = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=0.0,
            taxes=False,
        )

        trade_without_spread = usd_values_without_spread + asset_values_without_spread

        usd_values, asset_values, _ = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=balance,
            taxes=False,
        )

        assert np.all(usd_values >= 0.0)
        assert np.all(asset_values >= 0.0)
        trade = usd_values + asset_values

        assert np.all(trade <= trade_without_spread)
Beispiel #3
0
    def test_against_naive(
        self,
        closes,
        stop_loss,
        take_profit,
        target_usd_percentage,
        balancing_period,
        distribution,
        balance,
        tax_exemption,
    ):
        distributions = np.stack([distribution, distribution], axis=1)

        stop_loss_index = opt.get_stop_loss_index(closes, stop_loss)
        take_profit_index = opt.get_take_profit_index(closes, take_profit)

        usd_values1, asset_values1, buy_sizes1 = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=balance,
            taxes=True,
            tax_exemption=tax_exemption,
        )

        usd_values2, asset_values2, buy_sizes2 = opt.get_balanced_trade(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period,
            orderbook_distributions=distributions,
            balance=balance,
            taxes=True,
            tax_exemption=tax_exemption,
        )

        np.testing.assert_allclose(usd_values1, usd_values2)
        np.testing.assert_allclose(asset_values1, asset_values2)
        np.testing.assert_almost_equal(buy_sizes1, buy_sizes2)
Beispiel #4
0
    def test_naive_stop_loss_and_take_profit(
        self,
        closes,
        stop_loss,
        take_profit,
        target_usd_percentage,
    ):
        stop_loss_index = opt.get_stop_loss_index(closes, stop_loss)
        take_profit_index = opt.get_take_profit_index(closes, take_profit)

        usd_values, asset_values, _ = opt.get_balanced_trade_naive(
            closes,
            stop_loss_index,
            take_profit_index,
            stop_loss,
            take_profit,
            target_usd_percentage,
            balancing_period=len(closes) + 2,
            orderbook_distributions=np.array([[0.0, 0.0]]),
            balance=0.0,
            taxes=False,
        )

        assert np.all(usd_values >= 0.0)
        assert np.all(asset_values >= 0.0)

        trigger_i = min(stop_loss_index, take_profit_index)
        triggered = trigger_i < len(closes)

        trade = usd_values + asset_values

        if triggered:
            stop_loss_is_before_take_profit = stop_loss_index <= take_profit_index
            trigger_value = (
                stop_loss if stop_loss_is_before_take_profit else take_profit
            )

            np.testing.assert_allclose(
                trade[trigger_i:],
                trigger_value * (1.0 - target_usd_percentage) + target_usd_percentage,
            )
Beispiel #5
0
def simulate(
    params,
    moving_volumes,
    first_timestamps,
    get_buys_and_sells_fn,
    balance,
    k=20,
    assume_buy=True,
    return_separate=False,
):
    data_dir = os.path.abspath(
        os.path.join(constants.DATA_STORAGE_LOCATION,
                     constants.LOCAL_DATA_DIR))

    args = params["params"]
    aggregate_N, w = args[:2]
    strategy_N = aggregate_N * w

    secondary_args = params["secondary_params"]

    balancing_period = secondary_args["balancing_period"]
    displacement = secondary_args["displacement"]
    stop_loss = secondary_args["stop_loss"]
    take_profit = secondary_args["take_profit"]
    target_usd_percentage = secondary_args["target_usd_percentage"]

    k = min(k, len(moving_volumes.columns))
    idx_k = np.arange(k)

    pnl = np.zeros((len(moving_volumes.index), k + 1))
    pnl[0, :k] = 1.0 / k

    active_symbols = np.array([""] * k)
    timestamp_i = 0  # TODO: randomize first timestamp?
    timestamp = moving_volumes.index[timestamp_i]
    next_timestamps = np.array([timestamp] * k)

    idle_count = 0

    with tqdm(total=int(moving_volumes.index[-1] - moving_volumes.index[0]) //
              3600) as progress_bar:
        while timestamp < moving_volumes.index[-1]:
            li = next_timestamps == timestamp
            active_symbols[li] = ""
            volumes = moving_volumes.loc[timestamp].sort_values(
                ascending=False)

            i = 0

            for active_symbol_i in idx_k[li]:
                total_pnl = np.sum(pnl[timestamp_i, :])
                if pnl[timestamp_i, active_symbol_i] > total_pnl / k:
                    pnl[timestamp_i, k] += (pnl[timestamp_i, active_symbol_i] -
                                            total_pnl / k)
                    pnl[timestamp_i, active_symbol_i] = total_pnl / k
                else:
                    pnl_diff = min(
                        total_pnl / k - pnl[timestamp_i, active_symbol_i],
                        pnl[timestamp_i, k],
                    )

                    pnl[timestamp_i, k] -= pnl_diff
                    pnl[timestamp_i, active_symbol_i] += pnl_diff

                while i < len(volumes.index
                              ) and active_symbols[active_symbol_i] == "":
                    symbol = volumes.index[i]
                    i += 1

                    if symbol in active_symbols:
                        continue

                    first_timestamp = first_timestamps[symbol]

                    if first_timestamp > timestamp:
                        continue

                    (
                        aggregated_closes,
                        aggregated_lows,
                        aggregated_highs,
                        aggregated_times,
                        spread_data,
                    ) = data.load_data_for_symbol(data_dir,
                                                  symbol,
                                                  split_data=False,
                                                  displacement=displacement)

                    price_data_timestamp_i = utils.binary_search(
                        aggregated_times, timestamp)
                    aggregated_closes_up_to_timestamp = aggregated_closes[:
                                                                          price_data_timestamp_i]

                    buy = assume_buy

                    if len(aggregated_closes_up_to_timestamp) > strategy_N:
                        # ignore possible gaps
                        buy, _, N = get_buys_and_sells_fn(
                            aggregated_closes_up_to_timestamp[-(strategy_N +
                                                                1):],
                            *args,
                            as_boolean=True,
                            from_minute=False)
                        assert N == 1

                    if not buy:
                        continue

                    aggregated_closes = aggregated_closes[
                        price_data_timestamp_i - strategy_N:]
                    aggregated_lows = aggregated_lows[price_data_timestamp_i -
                                                      strategy_N:]
                    aggregated_highs = aggregated_highs[
                        price_data_timestamp_i - strategy_N:]
                    aggregated_times = aggregated_times[
                        price_data_timestamp_i - strategy_N:]

                    if len(aggregated_closes) <= strategy_N:
                        continue

                    # ignore possible gaps
                    buys, sells, N = get_buys_and_sells_fn(aggregated_closes,
                                                           *args,
                                                           from_minute=False)
                    aggregated_closes = aggregated_closes[-(N + 1):]
                    aggregated_lows = aggregated_lows[-(N + 1):]
                    aggregated_highs = aggregated_highs[-(N + 1):]
                    aggregated_times = aggregated_times[-(N + 1):]

                    tax_exemption = utils.get_leverage_from_symbol(symbol) == 1

                    _, trade_ends = opt.get_trades(buys, sells, aggregate_N,
                                                   False)

                    trade_end = trade_ends[0] if len(trade_ends) > 0 else 1

                    trade_closes = (aggregated_closes[1:trade_end + 1] /
                                    aggregated_closes[0])
                    trade_lows = (aggregated_lows[1:trade_end + 1] /
                                  aggregated_closes[0])
                    trade_highs = (aggregated_highs[1:trade_end + 1] /
                                   aggregated_closes[0])
                    trade_times = aggregated_times[1:trade_end + 1]

                    stop_loss_index = opt.get_stop_loss_index(
                        trade_lows, stop_loss)
                    take_profit_index = opt.get_take_profit_index(
                        trade_highs, take_profit)
                    trigger_i = min(stop_loss_index, take_profit_index)

                    usd_values, asset_values, _ = opt.get_balanced_trade(
                        trade_closes,
                        stop_loss_index,
                        take_profit_index,
                        stop_loss,
                        take_profit,
                        target_usd_percentage,
                        balancing_period,
                        spread_data,
                        balance * pnl[timestamp_i, active_symbol_i],
                        taxes=True,
                        tax_exemption=tax_exemption,
                        from_minute=False,
                    )

                    trade_values = usd_values + asset_values

                    if trigger_i == len(trade_closes):
                        trigger_i -= 1

                    next_timestamp = timestamp + float(
                        utils.get_smallest_divisible_larger_than(
                            int(trade_times[trigger_i] - timestamp),
                            aggregate_N * 3600,
                        ))

                    next_timestamps[active_symbol_i] = next_timestamp

                    # no need to substract 1 since these are used just with slice
                    trigger_timestamp_i = utils.binary_search(
                        moving_volumes.index.values, trade_times[trigger_i])
                    next_timestamp_i = utils.binary_search(
                        moving_volumes.index.values, next_timestamp)

                    pnl[timestamp_i + 1:trigger_timestamp_i,
                        active_symbol_i] = (np.interp(
                            moving_volumes.index.values[timestamp_i +
                                                        1:trigger_timestamp_i],
                            trade_times[:trigger_i + 1],
                            trade_values[:trigger_i + 1],
                        ) * pnl[timestamp_i, active_symbol_i])
                    pnl[trigger_timestamp_i:next_timestamp_i,
                        active_symbol_i] = pnl[trigger_timestamp_i - 1,
                                               active_symbol_i]

                    active_symbols[active_symbol_i] = symbol

                if active_symbols[active_symbol_i] == "":
                    idle_count += aggregate_N
                    # move next_timestamps[active_symbol_i] to next time
                    # based on aggregate_N
                    #   - the values of pnl (column active_symbol_i) from this
                    #     timestamp to the next should remain constant
                    next_timestamp = timestamp + aggregate_N * 3600.0
                    next_timestamps[active_symbol_i] = next_timestamp

                    # no need to substract 1 since this is used just with slice
                    next_timestamp_i = utils.binary_search(
                        moving_volumes.index.values, next_timestamp)

                    pnl[timestamp_i + 1:next_timestamp_i,
                        active_symbol_i] = pnl[timestamp_i, active_symbol_i]

            next_timestamp = np.min(next_timestamps)
            progress_bar.update(int(next_timestamp - timestamp) // 3600)
            timestamp = next_timestamp

            timestamp_i = (
                utils.binary_search(moving_volumes.index.values, timestamp) -
                1)
            assert (timestamp >= moving_volumes.index[-1]
                    or timestamp == moving_volumes.index[timestamp_i])

    if not return_separate:
        pnl = np.sum(pnl, axis=1)

    return pnl, idle_count
Beispiel #6
0
def test_get_take_profit_index_against_naive(highs, take_profit):
    assert opt.get_take_profit_index_naive(
        highs, take_profit
    ) == opt.get_take_profit_index(highs, take_profit)