예제 #1
0
 async def exchange_balances_extra_df(
         self,  # type: HummingbotApplication
         ex_balances: Dict[str, Decimal],
         ex_avai_balances: Dict[str, Decimal]):
     total_col_name = f"Total ({RateOracle.global_token_symbol})"
     allocated_total = Decimal("0")
     rows = []
     for token, bal in ex_balances.items():
         if bal == Decimal(0):
             continue
         avai = Decimal(ex_avai_balances.get(
             token.upper(),
             0)) if ex_avai_balances is not None else Decimal(0)
         allocated = f"{(bal - avai) / bal:.0%}"
         rate = await RateOracle.global_rate(token)
         rate = Decimal("0") if rate is None else rate
         global_value = rate * bal
         allocated_total += rate * (bal - avai)
         rows.append({
             "Asset": token.upper(),
             "Total": round(bal, 4),
             total_col_name: smart_round(global_value),
             "Allocated": allocated,
         })
     df = pd.DataFrame(
         data=rows, columns=["Asset", "Total", total_col_name, "Allocated"])
     df.sort_values(by=["Asset"], inplace=True)
     return df, allocated_total
예제 #2
0
 def active_positions_df(self) -> pd.DataFrame:
     columns = ["Symbol", "Type", "Fee Tier", "Amount", "Upper Price", "Lower Price", ""]
     data = []
     if len(self.active_positions) > 0:
         for position in self.active_positions:
             amount = self._base_token_amount if position in self.active_buys else self._quote_token_amount
             data.append([
                 position.trading_pair,
                 "Buy" if position in self.active_buys else "Sell",
                 position.fee_tier,
                 f"{smart_round(Decimal(str(amount)), 8)}",
                 smart_round(Decimal(str(position.upper_price)), 8),
                 smart_round(Decimal(str(position.lower_price)), 8),
                 "[In range]" if self._last_price >= position.lower_price and self._last_price <= position.upper_price else "[Out of range]"
             ])
     return pd.DataFrame(data=data, columns=columns)
예제 #3
0
    async def format_status(self) -> str:
        """
        Returns a status string formatted to display nicely on terminal. The strings composes of 4 parts: markets,
        assets, profitability and warnings(if any).
        """

        if self._arb_proposals is None:
            return "  The strategy is not ready, please try again later."
        # active_orders = self.market_info_to_active_orders.get(self._market_info, [])
        columns = ["Exchange", "Market", "Sell Price", "Buy Price", "Mid Price"]
        data = []
        for market_info in [self._market_info_1, self._market_info_2]:
            market, trading_pair, base_asset, quote_asset = market_info
            buy_price = await market.get_quote_price(trading_pair, True, self._order_amount)
            sell_price = await market.get_quote_price(trading_pair, False, self._order_amount)

            # check for unavailable price data
            buy_price = smart_round(Decimal(str(buy_price)), 8) if buy_price is not None else '-'
            sell_price = smart_round(Decimal(str(sell_price)), 8) if sell_price is not None else '-'
            mid_price = smart_round(((buy_price + sell_price) / 2), 8) if '-' not in [buy_price, sell_price] else '-'

            data.append([
                market.display_name,
                trading_pair,
                sell_price,
                buy_price,
                mid_price
            ])
        markets_df = pd.DataFrame(data=data, columns=columns)
        lines = []
        lines.extend(["", "  Markets:"] + ["    " + line for line in markets_df.to_string(index=False).split("\n")])

        assets_df = self.wallet_balance_data_frame([self._market_info_1, self._market_info_2])
        lines.extend(["", "  Assets:"] +
                     ["    " + line for line in str(assets_df).split("\n")])

        lines.extend(["", "  Profitability:"] + self.short_proposal_msg(self._arb_proposals))

        warning_lines = self.network_warning([self._market_info_1])
        warning_lines.extend(self.network_warning([self._market_info_2]))
        warning_lines.extend(self.balance_warning([self._market_info_1]))
        warning_lines.extend(self.balance_warning([self._market_info_2]))
        if len(warning_lines) > 0:
            lines.extend(["", "*** WARNINGS ***"] + warning_lines)

        return "\n".join(lines)
예제 #4
0
    async def market_trades_report(
            self,  # type: HummingbotApplication
            connector,
            days: float,
            market: str):
        trades: List[Trade] = await connector.get_my_trades(market, days)
        g_sym = RateOracle.global_token_symbol
        if not trades:
            self._notify(f"There is no trade on {market}.")
            return
        data = []
        amount_g_col_name = f" Amount ({g_sym})"
        columns = ["Time", " Side", " Price", "Amount", amount_g_col_name]
        trades = sorted(trades, key=lambda x: (x.trading_pair, x.timestamp))
        fees = {}  # a dict of token and total fee amount
        fee_usd = 0

        for trade in trades:
            time = f"{datetime.fromtimestamp(trade.timestamp / 1e3).strftime('%Y-%m-%d %H:%M:%S')} "
            side = "buy" if trade.side is TradeType.BUY else "sell"
            usd = await RateOracle.global_value(
                trade.trading_pair.split("-")[0], trade.amount)
            data.append([
                time, side,
                smart_round(trade.price),
                smart_round(trade.amount),
                round(usd)
            ])
            for fee in trade.trade_fee.flat_fees:
                if fee[0] not in fees:
                    fees[fee[0]] = fee[1]
                else:
                    fees[fee[0]] += fee[1]
                fee_usd += await RateOracle.global_value(fee[0], fee[1])

        lines = []
        df: pd.DataFrame = pd.DataFrame(data=data, columns=columns)
        lines.extend([f"  {market.upper()}"])
        lines.extend(
            ["    " + line for line in df.to_string(index=False).split("\n")])
        self._notify("\n" + "\n".join(lines))
        fee_text = ",".join(k + ": " + f"{v:.4f}" for k, v in fees.items())
        self._notify(
            f"\n  Total traded: {g_sym} {df[amount_g_col_name].sum():.0f}    "
            f"Fees: {fee_text} ({g_sym} {fee_usd:.2f})")
예제 #5
0
async def start_trade_monitor(trade_monitor):
    from hummingbot.client.hummingbot_application import HummingbotApplication
    hb = HummingbotApplication.main_application()
    trade_monitor.log("Trades: 0, Total P&L: 0.00, Return %: 0.00%")
    total_trades = 0
    return_pcts = []
    pnls = []
    quote_asset = ""

    while True:
        if hb.strategy_task is not None and not hb.strategy_task.done():
            if all(market.ready for market in hb.markets.values()):
                trades: List[TradeFill] = hb._get_trades_from_session(int(hb.init_time * 1e3),
                                                                      config_file_path=hb.strategy_file_name)
                if len(trades) > total_trades:
                    total_trades = len(trades)
                    market_info: Set[Tuple[str, str]] = set((t.market, t.symbol) for t in trades)
                    for market, symbol in market_info:
                        quote_asset = symbol.split("-")[1]  # Note that the qiote asset of the last pair is assumed to be the quote asset of P&L for simplicity
                        cur_trades = [t for t in trades if t.market == market and t.symbol == symbol]
                        cur_balances = await hb.get_current_balances(market)
                        perf = await calculate_performance_metrics(market, symbol, cur_trades, cur_balances)
                        return_pcts.append(perf.return_pct)
                        pnls.append(perf.total_pnl)
                    avg_return = sum(return_pcts) / len(return_pcts) if len(return_pcts) > 0 else s_decimal_0
                    total_pnls = sum(pnls)  # Note that this sum doesn't handles cases with different multiple pairs for simplisity
                    trade_monitor.log(f"Trades: {total_trades}, Total P&L: {smart_round(total_pnls)} {quote_asset}, Return %: {avg_return:.2%}")
                    
                    # Here we write the P&L to a file
                    data_set = {}
                    data_set['trades']=total_trades
                    data_set['total_pnl']=str(smart_round(total_pnls))+" " +quote_asset
                    data_set['return']=str(avg_return)

                    with open('data/totals.json', 'w') as outfile:
                        json.dump(data_set, outfile)
                    

                    
                    return_pcts.clear()
                    pnls.clear()
        await asyncio.sleep(2)  # sleeping for longer to manage resources
예제 #6
0
    async def format_status(self) -> str:
        """
        Returns a status string formatted to display nicely on terminal. The strings composes of 4 parts: market,
        assets, spread and warnings(if any).
        """
        if not self._connector_ready:
            return "UniswapV3 connector not ready."

        columns = ["Exchange", "Market", "Current Price"]
        data = []
        market, trading_pair, base_asset, quote_asset = self._market_info
        data.append([
            market.display_name,
            trading_pair,
            smart_round(Decimal(str(self._last_price)), 8)
        ])
        markets_df = pd.DataFrame(data=data, columns=columns)
        lines = []
        lines.extend(["", "  Markets:"] + ["    " + line for line in markets_df.to_string(index=False).split("\n")])

        # See if there're any active positions.
        if len(self.active_positions) > 0:
            df = self.active_positions_df()
            lines.extend(["", "  Positions:"] + ["    " + line for line in df.to_string(index=False).split("\n")])
        else:
            lines.extend(["", "  No active positions."])

        assets_df = self.wallet_balance_data_frame([self._market_info])
        lines.extend(["", "  Assets:"] +
                     ["    " + line for line in str(assets_df).split("\n")])

        warning_lines = self.network_warning([self._market_info])
        warning_lines.extend(self.balance_warning([self._market_info]))
        if len(warning_lines) > 0:
            lines.extend(["", "*** WARNINGS ***"] + warning_lines)

        return "\n".join(lines)
예제 #7
0
    def report_performance_by_market(
            self,  # type: HummingbotApplication
            market: str,
            trading_pair: str,
            perf: PerformanceMetrics,
            precision: int):
        lines = []
        base, quote = trading_pair.split("-")
        lines.extend([f"\n{market} / {trading_pair}"])

        trades_columns = ["", "buy", "sell", "total"]
        trades_data = [
            [
                f"{'Number of trades':<27}", perf.num_buys, perf.num_sells,
                perf.num_trades
            ],
            [
                f"{f'Total trade volume ({base})':<27}",
                smart_round(perf.b_vol_base, precision),
                smart_round(perf.s_vol_base, precision),
                smart_round(perf.tot_vol_base, precision)
            ],
            [
                f"{f'Total trade volume ({quote})':<27}",
                smart_round(perf.b_vol_quote, precision),
                smart_round(perf.s_vol_quote, precision),
                smart_round(perf.tot_vol_quote, precision)
            ],
            [
                f"{'Avg price':<27}",
                smart_round(perf.avg_b_price, precision),
                smart_round(perf.avg_s_price, precision),
                smart_round(perf.avg_tot_price, precision)
            ],
        ]
        trades_df: pd.DataFrame = pd.DataFrame(data=trades_data,
                                               columns=trades_columns)
        lines.extend(["", "  Trades:"] + [
            "    " + line
            for line in trades_df.to_string(index=False).split("\n")
        ])

        assets_columns = ["", "start", "current", "change"]
        assets_data = [
            [f"{base:<17}", "-", "-", "-"] if market in DERIVATIVES
            else  # No base asset for derivatives because they are margined
            [
                f"{base:<17}",
                smart_round(perf.start_base_bal, precision),
                smart_round(perf.cur_base_bal, precision),
                smart_round(perf.tot_vol_base, precision)
            ],
            [
                f"{quote:<17}",
                smart_round(perf.start_quote_bal, precision),
                smart_round(perf.cur_quote_bal, precision),
                smart_round(perf.tot_vol_quote, precision)
            ],
            [
                f"{trading_pair + ' price':<17}",
                smart_round(perf.start_price),
                smart_round(perf.cur_price),
                smart_round(perf.cur_price - perf.start_price)
            ],
            [f"{'Base asset %':<17}", "-", "-", "-"] if market in DERIVATIVES
            else  # No base asset for derivatives because they are margined
            [
                f"{'Base asset %':<17}", f"{perf.start_base_ratio_pct:.2%}",
                f"{perf.cur_base_ratio_pct:.2%}",
                f"{perf.cur_base_ratio_pct - perf.start_base_ratio_pct:.2%}"
            ],
        ]
        assets_df: pd.DataFrame = pd.DataFrame(data=assets_data,
                                               columns=assets_columns)
        lines.extend(["", "  Assets:"] + [
            "    " + line
            for line in assets_df.to_string(index=False).split("\n")
        ])

        perf_data = [[
            "Hold portfolio value    ",
            f"{smart_round(perf.hold_value, precision)} {quote}"
        ],
                     [
                         "Current portfolio value ",
                         f"{smart_round(perf.cur_value, precision)} {quote}"
                     ],
                     [
                         "Trade P&L               ",
                         f"{smart_round(perf.trade_pnl, precision)} {quote}"
                     ]]
        perf_data.extend([
            "Fees paid               ",
            f"{smart_round(fee_amount, precision)} {fee_token}"
        ] for fee_token, fee_amount in perf.fees.items())
        perf_data.extend([[
            "Total P&L               ",
            f"{smart_round(perf.total_pnl, precision)} {quote}"
        ], ["Return %                ", f"{perf.return_pct:.2%}"]])
        perf_df: pd.DataFrame = pd.DataFrame(data=perf_data)
        lines.extend(["", "  Performance:"] + [
            "    " + line for line in perf_df.to_string(
                index=False, header=False).split("\n")
        ])

        self._notify("\n".join(lines))
        with open('data/history.txt', 'w') as outfile:
            outfile.write("\n".join(lines))