예제 #1
0
    def get_performance_analysis_with_updated_balance(
            self,  # type: HummingbotApplication
    ) -> PerformanceAnalysis:
        performance_analysis = PerformanceAnalysis()
        dedup_set: Set[Tuple[str, str, bool]] = set()

        for market_symbol_pair in self.market_symbol_pairs:
            for is_base in [True, False]:
                for is_starting in [True, False]:
                    market_name = market_symbol_pair.market.name
                    asset_name = market_symbol_pair.base_asset if is_base else market_symbol_pair.quote_asset

                    if len(self.assets) == 0 or len(self.markets) == 0:
                        # Prevent KeyError '***SYMBOL***'
                        amount = self.starting_balances[asset_name][
                            market_name]
                    else:
                        amount = self.starting_balances[asset_name][market_name] if is_starting \
                            else self.balance_snapshot()[asset_name][market_name]
                    amount = float(amount)

                    # Adding this check to prevent assets in the same market to be added multiple times
                    if (market_name, asset_name, is_starting) not in dedup_set:
                        dedup_set.add((market_name, asset_name, is_starting))
                        performance_analysis.add_balances(
                            asset_name, amount, is_base, is_starting)

        return performance_analysis
    def test_calculate_trade_quote_delta_with_fees(self):
        test_trades = [("BUY", 1, 100), ("SELL", 0.9, 100), ("BUY", 1, 110),
                       ("SELL", 1, 115)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        raw_queried_trades = self.get_trades_from_session(start_time)
        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1,
            [self.trading_pair_tuple_1],
            raw_queried_trades,
        )

        expected_trade_performance_stats = {
            "portfolio_acquired_quote_value": Decimal("24111.45"),
            "portfolio_delta": Decimal("-823.55"),
            "portfolio_delta_percentage":
            Decimal("-3.302787246841788650491277320"),
            "portfolio_spent_quote_value": Decimal("24935.0")
        }

        expected_market_trading_pair_stats = {
            "acquired_quote_value":
            Decimal("24111.45"),
            "asset": {
                "DAI": {
                    "acquired": Decimal("202.9500000000000021555673912"),
                    "delta": Decimal("-7.0499999999999978444326088"),
                    "delta_percentage":
                    Decimal("-3.357142857142856116396480380"),
                    "spent": Decimal("210")
                },
                "WETH": {
                    "acquired": Decimal("207.8999999999999999562849684"),
                    "delta": Decimal("-7.1000000000000000437150316"),
                    "delta_percentage":
                    Decimal("-3.302325581395348857541875160"),
                    "spent": Decimal("215")
                }
            },
            "end_quote_rate":
            Decimal("115.0"),
            "spent_quote_value":
            Decimal("24935.0"),
            "starting_quote_rate":
            Decimal("1.0"),
            "trading_pair_delta":
            Decimal("-823.55000000000000287166124"),
            "trading_pair_delta_percentage":
            Decimal("-3.302787246841788662007865410")
        }

        self.assertDictEqual(trade_performance_stats,
                             expected_trade_performance_stats)
        self.assertDictEqual(
            expected_market_trading_pair_stats,
            market_trading_pair_stats[self.trading_pair_tuple_1])
    def test_calculate_asset_delta_from_trades(self):
        test_trades = [("BUY", 1, 100), ("SELL", 0.9, 110), ("BUY", 0.1, 100),
                       ("SELL", 1, 120)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        raw_queried_trades = self.get_trades_from_session(start_time)
        market_trading_pair_stats = performance_analysis.calculate_asset_delta_from_trades(
            self.strategy_1, [self.trading_pair_tuple_1], raw_queried_trades)

        expected_stats = {
            'asset': {
                'DAI': {
                    'acquired': Decimal('216.8100000000000023724772146'),
                    'spent': Decimal('110.0000000000000005551115123')
                },
                'WETH': {
                    'acquired': Decimal('197.9999999999999999583666366'),
                    'spent': Decimal('230')
                }
            },
            'trade_count': 4,
            'starting_quote_rate': Decimal('1.0')
        }
        self.assertDictEqual(
            expected_stats,
            market_trading_pair_stats[self.trading_pair_tuple_1])
    def test_calculate_trade_performance(self):
        test_trades = [("BUY", 2, 100), ("SELL", 0.9, 110), ("BUY", 0.5, 105),
                       ("SELL", 1, 120)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        raw_queried_trades = self.get_trades_from_session(start_time)
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1,
            [self.trading_pair_tuple_1],
            raw_queried_trades,
        )

        expected_trade_performance_stats = {
            'portfolio_acquired_quote_value': Decimal('23556.06'),
            'portfolio_delta': Decimal('-3146.44'),
            'portfolio_delta_percentage':
            Decimal('-11.78331616889804325437693100'),
            'portfolio_spent_quote_value': Decimal('26702.5')
        }
        expected_market_trading_pair_stats = {
            'acquired_quote_value':
            Decimal('23556.06'),
            'asset': {
                'DAI': {
                    'acquired': Decimal('216.8100000000000023724772146'),
                    'delta': Decimal('-35.6899999999999976275227854'),
                    'delta_percentage':
                    Decimal('-14.13465346534653371387041006'),
                    'spent': Decimal('252.5')
                },
                'WETH': {
                    'acquired': Decimal('202.9499999999999999573258025'),
                    'delta': Decimal('-27.0500000000000000426741975'),
                    'delta_percentage':
                    Decimal('-11.76086956521739132290182500'),
                    'spent': Decimal('230')
                }
            },
            'end_quote_rate':
            Decimal('115.0'),
            'spent_quote_value':
            Decimal('26702.5'),
            'starting_quote_rate':
            Decimal('2.0'),
            'trading_pair_delta':
            Decimal('-3146.44000000000000253505550'),
            'trading_pair_delta_percentage':
            Decimal('-11.78331616889804326387063196')
        }

        self.assertDictEqual(expected_trade_performance_stats,
                             trade_performance_stats)
        self.assertDictEqual(
            expected_market_trading_pair_stats,
            market_trading_pair_stats[self.trading_pair_tuple_1])
 def test_nan_starting(self):
     """ Test the case where the starting balance is 0. """
     performance_analysis = PerformanceAnalysis()
     performance_analysis.add_balances("WETH", 0, True, True)
     performance_analysis.add_balances("DAI", 0, False, True)
     performance_analysis.add_balances("WETH", 0.3, True, False)
     performance_analysis.add_balances("DAI", 70, False, False)
     calculated_percent = performance_analysis.compute_profitability(50)
     self.assertTrue(math.isnan(calculated_percent), "Starting value of 0 test failed.")
예제 #6
0
    def get_performance_analysis_with_updated_balance(
            self,  # type: HummingbotApplication
    ) -> PerformanceAnalysis:
        performance_analysis = PerformanceAnalysis()

        for market_symbol_pair in self.market_symbol_pairs:
            for is_base in [True, False]:
                for is_starting in [True, False]:
                    market_name = market_symbol_pair.market.name
                    asset_name = market_symbol_pair.base_asset if is_base else market_symbol_pair.quote_asset
                    amount = self.starting_balances[asset_name][market_name] if is_starting \
                        else self.balance_snapshot()[asset_name][market_name]
                    amount = float(amount)
                    performance_analysis.add_balances(asset_name, amount,
                                                      is_base, is_starting)

        return performance_analysis
예제 #7
0
 def _calculate_trade_performance(
         self,  # type: HummingbotApplication
 ) -> Tuple[Dict, Dict]:
     raw_queried_trades = self._get_trades_from_session(self.init_time)
     current_strategy_name: str = self.markets_recorder.strategy_name
     performance_analysis: PerformanceAnalysis = PerformanceAnalysis()
     trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
         current_strategy_name, self.market_trading_pair_tuples,
         raw_queried_trades, self.starting_balances)
     return trade_performance_stats, market_trading_pair_stats
    def test_multiple_market(self):
        test_trades_1 = [("BUY", 1, 100), ("SELL", 0.9, 100), ("BUY", 1, 110),
                         ("SELL", 1, 115)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades_1, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)
        test_trades_2 = [("BUY", 2, 100), ("SELL", 0.9, 110),
                         ("BUY", 0.5, 105), ("SELL", 1, 120)]
        self.save_trade_fill_records(test_trades_2, self.trading_pair_tuple_2,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        raw_queried_trades = self.get_trades_from_session(start_time)
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1,
            [self.trading_pair_tuple_1, self.trading_pair_tuple_2],
            raw_queried_trades)

        expected_trade_performance_stats = {
            'portfolio_acquired_quote_value': Decimal('49025.529473684214'),
            'portfolio_delta': Decimal('-4151.707368421049'),
            'portfolio_delta_percentage':
            Decimal('-7.807301798602976761843492980'),
            'portfolio_spent_quote_value': Decimal('53177.236842105263')
        }
        expected_markettrading_pair_stats_1 = {
            'acquired_quote_value':
            Decimal('24111.45'),
            'asset': {
                'DAI': {
                    'acquired': Decimal('202.9500000000000021555673912'),
                    'delta': Decimal('-7.0499999999999978444326088'),
                    'delta_percentage':
                    Decimal('-3.357142857142856116396480380'),
                    'spent': Decimal('210')
                },
                'WETH': {
                    'acquired': Decimal('207.8999999999999999562849684'),
                    'delta': Decimal('-7.1000000000000000437150316'),
                    'delta_percentage':
                    Decimal('-3.302325581395348857541875160'),
                    'spent': Decimal('215')
                }
            },
            'end_quote_rate':
            Decimal('115.0'),
            'spent_quote_value':
            Decimal('24935.0'),
            'starting_quote_rate':
            Decimal('1.0'),
            'trading_pair_delta':
            Decimal('-823.55000000000000287166124'),
            'trading_pair_delta_percentage':
            Decimal('-3.302787246841788662007865410')
        }
        expected_markettrading_pair_stats_2 = {
            'acquired_quote_value':
            Decimal('24914.079473684214'),
            'asset': {
                'ETH': {
                    'acquired': Decimal('202.9499999999999999573258025'),
                    'delta': Decimal('-27.0500000000000000426741975'),
                    'delta_percentage':
                    Decimal('-11.76086956521739132290182500'),
                    'spent': Decimal('230')
                },
                'USDC': {
                    'acquired': Decimal('216.8100000000000023724772146'),
                    'delta': Decimal('-35.6899999999999976275227854'),
                    'delta_percentage':
                    Decimal('-14.13465346534653371387041006'),
                    'spent': Decimal('252.5')
                }
            },
            'end_quote_rate':
            Decimal('110.0'),
            'spent_quote_value':
            Decimal('28242.236842105263'),
            'starting_quote_rate':
            Decimal('2.0'),
            'trading_pair_delta':
            Decimal('-3011.19000000000000232168451'),
            'trading_pair_delta_percentage':
            Decimal('-11.78432638685060171146339697')
        }
        self.assertDictEqual(expected_trade_performance_stats,
                             trade_performance_stats)
        self.assertDictEqual(
            expected_markettrading_pair_stats_1,
            market_trading_pair_stats[self.trading_pair_tuple_1])
        self.assertDictEqual(
            expected_markettrading_pair_stats_2,
            market_trading_pair_stats[self.trading_pair_tuple_2])
    def test_basic_one_ex(self):
        """ Test performance analysis on a one exchange balance. """
        performance_analysis = PerformanceAnalysis()
        starting_weth = 0.5
        starting_dai = 60
        current_weth = 0.4
        current_dai = 70

        performance_analysis.add_balances("WETH", starting_weth, True, True)
        performance_analysis.add_balances("DAI", starting_dai, False, True)
        performance_analysis.add_balances("WETH", current_weth, True, False)
        performance_analysis.add_balances("DAI", current_dai, False, False)

        calculated_starting_token, calculated_starting_amount = performance_analysis.compute_starting(
            self._price)
        calculated_current_token, calculated_current_amount = performance_analysis.compute_current(
            self._price)
        calculated_delta_token, calculated_delta_amount = performance_analysis.compute_delta(
            self._price)
        calculated_return = performance_analysis.compute_return(self._price)

        expected_starting_amount = (starting_weth * self._price) + starting_dai
        expected_current_amount = (current_weth * self._price) + current_dai
        expected_delta_amount = expected_current_amount - expected_starting_amount
        expected_return = (
            (expected_current_amount / expected_starting_amount) - 1) * 100

        self.assertEqual(
            calculated_starting_token,
            "DAI",
            msg=
            "Basic one exchange test: expected starting token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_starting_amount,
            expected_starting_amount,
            msg=
            "Basic one exchange test: expected starting amount incorrectly determined."
        )
        self.assertEqual(
            calculated_current_token,
            "DAI",
            msg=
            "Basic one exchange test: expected current token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_current_amount,
            expected_current_amount,
            msg=
            "Basic one exchange test: expected current amount incorrectly determined."
        )
        self.assertEqual(
            calculated_delta_token,
            "DAI",
            msg=
            "Basic one exchange test: expected delta token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_delta_amount,
            expected_delta_amount,
            msg=
            "Basic one exchange test: expected delta amount incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_return,
            expected_return,
            msg="Basic one exchange test: return incorrectly determined.")
 def test_different_tokens_two_ex(self):
     """ Test performance analysis on a two exchange balance with different currencies trading. Note that this test
     will not work as the config file that contains the conversion has not been loaded."""
     performance_analysis = PerformanceAnalysis()
     performance_analysis.add_balances("WETH", 0.5, True, True)
     performance_analysis.add_balances("DAI", 60, False, True)
     performance_analysis.add_balances("ETH", 0.7, True, True)
     performance_analysis.add_balances("USD", 50, False, True)
     performance_analysis.add_balances("WETH", 0.4, True, False)
     performance_analysis.add_balances("DAI", 70, False, False)
     performance_analysis.add_balances("ETH", 0.3, True, False)
     performance_analysis.add_balances("USD", 70, False, False)
     calculated_percent = performance_analysis.compute_profitability(50)
     expected_percent = (((0.7 * 50) + 140)/((1.2 * 50) + 110) - 1) * 100
     self.assertAlmostEquals(calculated_percent, expected_percent, msg="Two diff token test failed.", delta=0.1)
    def test_calculate_trade_performance(self):
        test_trades = [("BUY", 100, 2), ("SELL", 110, 0.9), ("BUY", 105, 0.5),
                       ("SELL", 120, 1)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        raw_queried_trades = self.get_trades_from_session(start_time)
        m_name = self.trading_pair_tuple_1.market.name
        starting_balances = {
            "DAI": {
                m_name: Decimal("1000")
            },
            "WETH": {
                m_name: Decimal("5")
            }
        }
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1, [self.trading_pair_tuple_1], raw_queried_trades,
            starting_balances)

        expected_trade_performance_stats = {
            'portfolio_acquired_quote_value': Decimal('501.435'),
            'portfolio_spent_quote_value': Decimal('471.0'),
            'portfolio_delta': Decimal('30.435'),
            'portfolio_delta_percentage':
            Decimal('1.932380952380952380952380952')
        }
        expected_market_trading_pair_stats = {
            'starting_quote_rate':
            Decimal('100.0'),
            'asset': {
                'WETH': {
                    'spent': Decimal('1.900000000000000022204460492'),
                    'acquired': Decimal('2.474999999999999999479582957'),
                    'delta': Decimal('0.574999999999999977275122465'),
                    'delta_percentage':
                    Decimal('30.26315789473684055554481720')
                },
                'DAI': {
                    'spent': Decimal('252.5'),
                    'acquired': Decimal('216.8100000000000023724772146'),
                    'delta': Decimal('-35.6899999999999976275227854'),
                    'delta_percentage':
                    Decimal('-14.13465346534653371387041006')
                }
            },
            'trade_count':
            4,
            'end_quote_rate':
            Decimal('115.0'),
            'acquired_quote_value':
            Decimal('501.435'),
            'spent_quote_value':
            Decimal('471.0'),
            'starting_quote_value':
            Decimal('1575.0'),
            'trading_pair_delta':
            Decimal('30.4349999999999997591162981'),
            'trading_pair_delta_percentage':
            Decimal('1.932380952380952365658177657')
        }
        self.assertDictEqual(expected_trade_performance_stats,
                             trade_performance_stats)
        self.assertDictEqual(
            expected_market_trading_pair_stats,
            market_trading_pair_stats[self.trading_pair_tuple_1])
예제 #12
0
    def test_basic_two_ex(self):
        """ Test performance analysis on a two exchange balance with the same currencies trading in both exchanges. """
        performance_analysis = PerformanceAnalysis()
        starting_weth_1 = 0.5
        starting_dai_1 = 60
        starting_weth_2 = 0.7
        starting_dai_2 = 50
        current_weth_1 = 0.4
        current_dai_1 = 70
        current_weth_2 = 0.3
        current_dai_2 = 70

        performance_analysis.add_balances("WETH", starting_weth_1, True, True)
        performance_analysis.add_balances("DAI", starting_dai_1, False, True)
        performance_analysis.add_balances("WETH", starting_weth_2, True, True)
        performance_analysis.add_balances("DAI", starting_dai_2, False, True)
        performance_analysis.add_balances("WETH", current_weth_1, True, False)
        performance_analysis.add_balances("DAI", current_dai_1, False, False)
        performance_analysis.add_balances("WETH", current_weth_2, True, False)
        performance_analysis.add_balances("DAI", current_dai_2, False, False)

        calculated_starting_token, calculated_starting_amount = performance_analysis.compute_starting(
            self._price)
        calculated_current_token, calculated_current_amount = performance_analysis.compute_current(
            self._price)
        calculated_delta_token, calculated_delta_amount = performance_analysis.compute_delta(
            self._price)
        calculated_return = performance_analysis.compute_return(self._price)

        starting_weth = starting_weth_1 + starting_weth_2
        starting_dai = starting_dai_1 + starting_dai_2
        current_weth = current_weth_1 + current_weth_2
        current_dai = current_dai_1 + current_dai_2

        expected_starting_amount = (starting_weth * self._price) + starting_dai
        expected_current_amount = (current_weth * self._price) + current_dai
        expected_delta_amount = expected_current_amount - expected_starting_amount
        expected_return = (
            (expected_current_amount / expected_starting_amount) - 1) * 100

        self.assertEqual(
            calculated_starting_token,
            "DAI",
            msg=
            "Basic two exchange test: expected starting token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_starting_amount,
            expected_starting_amount,
            msg=
            "Basic two exchange test: expected starting amount incorrectly determined."
        )
        self.assertEqual(
            calculated_current_token,
            "DAI",
            msg=
            "Basic two exchange test: expected current token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_current_amount,
            expected_current_amount,
            msg=
            "Basic two exchange test: expected current amount incorrectly determined."
        )
        self.assertEqual(
            calculated_delta_token,
            "DAI",
            msg=
            "Basic two exchange test: expected delta token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_delta_amount,
            expected_delta_amount,
            msg=
            "Basic two exchange test: expected delta amount incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_return,
            expected_return,
            msg="Basic two exchange test: return incorrectly determined.")
예제 #13
0
    def trade_performance_report(
            self,  # type: HummingbotApplication
    ) -> pd.DataFrame:

        if len(self.market_trading_pair_tuples) == 0:
            self._notify(
                "  Performance analysis is not available before bot starts")
            return

        try:
            raw_queried_trades = self._get_trades_from_session(self.init_time)
            current_strategy_name: str = self.markets_recorder.strategy_name
            primary_quote_asset: str = self.market_trading_pair_tuples[
                0].quote_asset.upper()
            performance_analysis: PerformanceAnalysis = PerformanceAnalysis()
            trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
                current_strategy_name,
                self.market_trading_pair_tuples,
                raw_queried_trades,
            )
            trade_performance_status_line = []
            market_df_data: Set[Tuple[str, str, float, float, str,
                                      str]] = set()
            market_df_columns = [
                "Market", "Trading_Pair", "Start_Price", "End_Price",
                "Total_Value_Delta", "Profit"
            ]

            for market_trading_pair_tuple, trading_pair_stats in market_trading_pair_stats.items(
            ):
                market_df_data.add((
                    market_trading_pair_tuple.market.display_name,
                    market_trading_pair_tuple.trading_pair.upper(),
                    float(trading_pair_stats["starting_quote_rate"]),
                    float(trading_pair_stats["end_quote_rate"]),
                    f"{trading_pair_stats['trading_pair_delta']:.8f} {primary_quote_asset}",
                    f"{trading_pair_stats['trading_pair_delta_percentage']:.3f} %"
                ))

            inventory_df: pd.DataFrame = self.balance_comparison_data_frame(
                market_trading_pair_stats)
            market_df: pd.DataFrame = pd.DataFrame(data=list(market_df_data),
                                                   columns=market_df_columns)
            portfolio_delta: Decimal = trade_performance_stats[
                "portfolio_delta"]
            portfolio_delta_percentage: Decimal = trade_performance_stats[
                "portfolio_delta_percentage"]

            trade_performance_status_line.extend(["", "  Inventory:"] + [
                "    " + line for line in inventory_df.to_string().split("\n")
            ])
            trade_performance_status_line.extend(
                ["", "  Market Trading Pair Performance:"] +
                ["    " + line for line in market_df.to_string().split("\n")])

            trade_performance_status_line.extend([
                "", "  Portfolio Performance:"
            ] + [
                f"    Quote Value Delta: {portfolio_delta:.7g} {primary_quote_asset}"
            ] + [f"    Delta Percentage: {portfolio_delta_percentage:.3f} %"])

            self._notify("\n".join(trade_performance_status_line))

        except Exception:
            self.logger().error(
                "Unexpected error running performance analysis.",
                exc_info=True)
            self._notify("Error running performance analysis")
 def test_basic_one_ex(self):
     """ Test performance analysis on a one exchange balance. """
     performance_analysis = PerformanceAnalysis()
     performance_analysis.add_balances("WETH", 0.5, True, True)
     performance_analysis.add_balances("DAI", 60, False, True)
     performance_analysis.add_balances("WETH", 0.4, True, False)
     performance_analysis.add_balances("DAI", 70, False, False)
     calculated_percent = performance_analysis.compute_profitability(50)
     expected_percent = (((0.4 * 50) + 70)/((0.5 * 50) + 60) - 1) * 100
     self.assertEqual(calculated_percent, expected_percent, "Basic one ex test failed.")
    def test_calculate_trade_quote_delta_with_fees(self):
        test_trades = [("BUY", 100, 1), ("SELL", 100, 0.9), ("BUY", 110, 1),
                       ("SELL", 115, 1)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        raw_queried_trades = self.get_trades_from_session(start_time)
        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        m_name = self.trading_pair_tuple_1.market.name
        starting_balances = {
            "DAI": {
                m_name: Decimal("1000")
            },
            "WETH": {
                m_name: Decimal("5")
            }
        }
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1, [self.trading_pair_tuple_1], raw_queried_trades,
            starting_balances)

        expected_trade_performance_stats = {
            'portfolio_acquired_quote_value': Decimal('430.65'),
            'portfolio_spent_quote_value': Decimal('428.5'),
            'portfolio_delta': Decimal('2.15'),
            'portfolio_delta_percentage':
            Decimal('0.1365079365079365079365079365')
        }

        expected_market_trading_pair_stats = {
            'starting_quote_rate':
            Decimal('100.0'),
            'asset': {
                'WETH': {
                    'spent': Decimal('1.900000000000000022204460492'),
                    'acquired': Decimal('1.979999999999999999583666366'),
                    'delta': Decimal('0.079999999999999977379205874'),
                    'delta_percentage':
                    Decimal('4.210526315789472444435853800')
                },
                'DAI': {
                    'spent': Decimal('210'),
                    'acquired': Decimal('202.9500000000000021555673912'),
                    'delta': Decimal('-7.0499999999999978444326088'),
                    'delta_percentage':
                    Decimal('-3.357142857142856116396480380')
                }
            },
            'trade_count':
            4,
            'end_quote_rate':
            Decimal('115.0'),
            'acquired_quote_value':
            Decimal('430.65'),
            'spent_quote_value':
            Decimal('428.5'),
            'starting_quote_value':
            Decimal('1575.0'),
            'trading_pair_delta':
            Decimal('2.1499999999999995541760667'),
            'trading_pair_delta_percentage':
            Decimal('0.1365079365079364796302264571')
        }

        self.assertDictEqual(trade_performance_stats,
                             expected_trade_performance_stats)
        self.assertDictEqual(
            expected_market_trading_pair_stats,
            market_trading_pair_stats[self.trading_pair_tuple_1])
예제 #16
0
    def test_different_tokens_two_ex(self):
        """ Test performance analysis on a two exchange balance with different currencies trading. Note that this test
        will not work as the config file that contains the conversion has not been loaded."""
        performance_analysis = PerformanceAnalysis()
        starting_weth_1 = 0.5
        starting_dai_1 = 60
        starting_eth_2 = 0.7
        starting_usdc_2 = 50
        current_weth_1 = 0.4
        current_dai_1 = 70
        current_eth_2 = 0.3
        current_usdc_2 = 70

        performance_analysis.add_balances("WETH", starting_weth_1, True, True)
        performance_analysis.add_balances("DAI", starting_dai_1, False, True)
        performance_analysis.add_balances("ETH", starting_eth_2, True, True)
        performance_analysis.add_balances("USDC", starting_usdc_2, False, True)
        performance_analysis.add_balances("WETH", current_weth_1, True, False)
        performance_analysis.add_balances("DAI", current_dai_1, False, False)
        performance_analysis.add_balances("ETH", current_eth_2, True, False)
        performance_analysis.add_balances("USDC", current_usdc_2, False, False)

        calculated_starting_token, calculated_starting_amount = performance_analysis.compute_starting(
            self._price)
        calculated_current_token, calculated_current_amount = performance_analysis.compute_current(
            self._price)
        calculated_delta_token, calculated_delta_amount = performance_analysis.compute_delta(
            self._price)
        calculated_return = performance_analysis.compute_return(self._price)

        starting_weth = starting_weth_1 + starting_eth_2
        starting_dai = starting_dai_1 + (starting_usdc_2 * self._usdc_price *
                                         (1 / self._dai_price))
        current_weth = current_weth_1 + current_eth_2
        current_dai = current_dai_1 + (current_usdc_2 * self._usdc_price *
                                       (1 / self._dai_price))

        expected_starting_amount = (starting_weth * self._price) + starting_dai
        expected_current_amount = (current_weth * self._price) + current_dai
        expected_delta_amount = expected_current_amount - expected_starting_amount
        expected_return = (
            (expected_current_amount / expected_starting_amount) - 1) * 100

        self.assertEqual(
            calculated_starting_token,
            "DAI",
            msg=
            "Two exchange test w/ diff tokens: expected starting token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_starting_amount,
            expected_starting_amount,
            msg="Two exchange test w/ diff tokens: "
            "expected starting amount incorrectly determined.")
        self.assertEqual(
            calculated_current_token,
            "DAI",
            msg=
            "Two exchange test w/ diff tokens: expected current token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_current_amount,
            expected_current_amount,
            msg=
            "Two exchange test w/ diff tokens: expected current amount incorrectly determined."
        )
        self.assertEqual(
            calculated_delta_token,
            "DAI",
            msg=
            "Two exchange test w/ diff tokens: expected delta token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_delta_amount,
            expected_delta_amount,
            msg=
            "Two exchange test w/ diff tokens: expected delta amount incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_return,
            expected_return,
            msg=
            "Two exchange test w/ diff tokens: return incorrectly determined.")
예제 #17
0
    def test_nan_starting(self):
        """ Test the case where the starting balance is 0. """
        performance_analysis = PerformanceAnalysis()
        starting_weth = 0
        starting_dai = 0
        current_weth = 0.3
        current_dai = 70

        performance_analysis.add_balances("WETH", starting_weth, True, True)
        performance_analysis.add_balances("DAI", starting_dai, False, True)
        performance_analysis.add_balances("WETH", current_weth, True, False)
        performance_analysis.add_balances("DAI", current_dai, False, False)

        calculated_starting_token, calculated_starting_amount = performance_analysis.compute_starting(
            self._price)
        calculated_current_token, calculated_current_amount = performance_analysis.compute_current(
            self._price)
        calculated_delta_token, calculated_delta_amount = performance_analysis.compute_delta(
            self._price)
        calculated_return = performance_analysis.compute_return(self._price)

        expected_starting_amount = (starting_weth * self._price) + starting_dai
        expected_current_amount = (current_weth * self._price) + current_dai
        expected_delta_amount = expected_current_amount - expected_starting_amount

        self.assertEqual(
            calculated_starting_token,
            "DAI",
            msg=
            "Starting value of 0 test: expected starting token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_starting_amount,
            expected_starting_amount,
            msg=
            "Starting value of 0 test: expected starting amount incorrectly determined."
        )
        self.assertEqual(
            calculated_current_token,
            "DAI",
            msg=
            "Starting value of 0 test: expected current token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_current_amount,
            expected_current_amount,
            msg=
            "Starting value of 0 test: expected current amount incorrectly determined."
        )
        self.assertEqual(
            calculated_delta_token,
            "DAI",
            msg=
            "Starting value of 0 test: expected delta token incorrectly determined."
        )
        self.assertAlmostEquals(
            calculated_delta_amount,
            expected_delta_amount,
            msg=
            "Starting value of 0 test: expected delta amount incorrectly determined."
        )
        self.assertTrue(
            math.isnan(calculated_return),
            "Starting value of 0 test: return incorrectly determined.")
    def test_multiple_market(self):
        test_trades_1 = [("BUY", 100, 1), ("SELL", 100, 0.9), ("BUY", 110, 1),
                         ("SELL", 115, 1)]
        start_time = int(time.time() * 1e3) - 100000
        self.save_trade_fill_records(test_trades_1, self.trading_pair_tuple_1,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)
        test_trades_2 = [("BUY", 100, 2), ("SELL", 110, 0.9),
                         ("BUY", 105, 0.5), ("SELL", 120, 1)]
        self.save_trade_fill_records(test_trades_2, self.trading_pair_tuple_2,
                                     OrderType.MARKET.name, start_time,
                                     self.strategy_1)

        performance_analysis = PerformanceAnalysis(sql=self.trade_fill_sql)
        raw_queried_trades = self.get_trades_from_session(start_time)
        m_name_1 = self.trading_pair_tuple_1.market.name
        m_name_2 = self.trading_pair_tuple_2.market.name

        starting_balances = {
            "DAI": {
                m_name_1: Decimal("1000")
            },
            "WETH": {
                m_name_1: Decimal("5")
            },
            "USDC": {
                m_name_2: Decimal("500")
            },
            "ETH": {
                m_name_2: Decimal("1")
            }
        }
        trade_performance_stats, market_trading_pair_stats = performance_analysis.calculate_trade_performance(
            self.strategy_1,
            [self.trading_pair_tuple_1, self.trading_pair_tuple_2],
            raw_queried_trades, starting_balances)

        expected_trade_performance_stats = {
            'portfolio_acquired_quote_value': Decimal('971.1900000000001'),
            'portfolio_spent_quote_value': Decimal('938.5789473684211'),
            'portfolio_delta': Decimal('32.6110526315790'),
            'portfolio_delta_percentage':
            Decimal('1.449888849888852211888512345')
        }
        expected_markettrading_pair_stats_1 = {
            'starting_quote_rate':
            Decimal('100.0'),
            'asset': {
                'WETH': {
                    'spent': Decimal('1.900000000000000022204460492'),
                    'acquired': Decimal('1.979999999999999999583666366'),
                    'delta': Decimal('0.079999999999999977379205874'),
                    'delta_percentage':
                    Decimal('4.210526315789472444435853800')
                },
                'DAI': {
                    'spent': Decimal('210'),
                    'acquired': Decimal('202.9500000000000021555673912'),
                    'delta': Decimal('-7.0499999999999978444326088'),
                    'delta_percentage':
                    Decimal('-3.357142857142856116396480380')
                }
            },
            'trade_count':
            4,
            'end_quote_rate':
            Decimal('115.0'),
            'acquired_quote_value':
            Decimal('430.65'),
            'spent_quote_value':
            Decimal('428.5'),
            'starting_quote_value':
            Decimal('1575.0'),
            'trading_pair_delta':
            Decimal('2.1499999999999995541760667'),
            'trading_pair_delta_percentage':
            Decimal('0.1365079365079364796302264571')
        }
        expected_markettrading_pair_stats_2 = {
            'starting_quote_rate':
            Decimal('100.0'),
            'asset': {
                'ETH': {
                    'spent': Decimal('1.900000000000000022204460492'),
                    'acquired': Decimal('2.474999999999999999479582957'),
                    'delta': Decimal('0.574999999999999977275122465'),
                    'delta_percentage':
                    Decimal('30.26315789473684055554481720')
                },
                'USDC': {
                    'spent': Decimal('252.5'),
                    'acquired': Decimal('216.8100000000000023724772146'),
                    'delta': Decimal('-35.6899999999999976275227854'),
                    'delta_percentage':
                    Decimal('-14.13465346534653371387041006')
                }
            },
            'trade_count':
            4,
            'end_quote_rate':
            Decimal('110.0'),
            'acquired_quote_value':
            Decimal('540.5400000000001'),
            'spent_quote_value':
            Decimal('510.0789473684211'),
            'starting_quote_value':
            Decimal('674.2105263157895'),
            'trading_pair_delta':
            Decimal('27.5599999999999998727406858'),
            'trading_pair_delta_percentage':
            Decimal('4.518032786885245880777161607')
        }
        self.assertDictEqual(expected_trade_performance_stats,
                             trade_performance_stats)
        self.assertDictEqual(
            expected_markettrading_pair_stats_1,
            market_trading_pair_stats[self.trading_pair_tuple_1])
        self.assertDictEqual(
            expected_markettrading_pair_stats_2,
            market_trading_pair_stats[self.trading_pair_tuple_2])
 def test_basic_two_ex(self):
     """ Test performance analysis on a two exchange balance with the same currencies trading in both exchanges. """
     performance_analysis = PerformanceAnalysis()
     performance_analysis.add_balances("WETH", 0.5, True, True)
     performance_analysis.add_balances("DAI", 60, False, True)
     performance_analysis.add_balances("WETH", 0.7, True, True)
     performance_analysis.add_balances("DAI", 50, False, True)
     performance_analysis.add_balances("WETH", 0.4, True, False)
     performance_analysis.add_balances("DAI", 70, False, False)
     performance_analysis.add_balances("WETH", 0.3, True, False)
     performance_analysis.add_balances("DAI", 70, False, False)
     calculated_percent = performance_analysis.compute_profitability(50)
     expected_percent = (((0.7 * 50) + 140)/((1.2 * 50) + 110) - 1) * 100
     self.assertEqual(calculated_percent, expected_percent, "Basic one ex test failed.")