A New Metric for Evaluating Trading Bot Performance?

in #tradingbotlast month

A New Metric for Evaluating Trading Bot Performance?

Hey all, I've been working on a new metric to better measure the performance of trading bots, particularly for something like Gunbot. I've always felt that traditional metrics like ROI (Return on Investment), CAGR (Compound Annual Growth Rate), or even the Sortino Ratio don't always give you the full picture when it comes to automated trading. They can be tricky to use, understand, and especially difficult when you're trying to compare the performance of different strategies across various assets.

Why Traditional Metrics Fall Short

  • ROI: Sure, ROI gives you a snapshot of profitability, but it doesn't tell you how long your capital was tied up or what kind of risk exposure you had. Two bots with the same ROI could have wildly different levels of risk or time commitment.

  • CAGR: I get it—CAGR is great for long-term investments, but when you're running a trading bot that's making decisions daily (or even hourly), it's tough to rely on an annualized metric. It’s hard to apply something designed for multi-year investments to something as dynamic as crypto trading.

  • Sortino Ratio: The Sortino Ratio is better than Sharpe when it comes to ignoring upside volatility, but it’s still not the easiest thing to explain or compare across different strategies. It's especially tricky when the assets you're trading have different volatility profiles, like comparing Bitcoin to a stablecoin or traditional stocks.

Because of these limitations, I started working on something that could more accurately reflect how well a bot is performing based on capital efficiency and duration of trades. And that’s where the Return on Bot (RoB) idea came in.

Return on Bot (RoB)

RoB is designed to give you a deeper insight into how effectively your bot is using the capital you’ve allocated. It factors in things like capital utilization over time, maximum capital utilized, and of course, the net profit generated. What I like about this is that it doesn’t just focus on profits but also on how efficiently those profits were made.

If you're using a crypto trading bot like Gunbot, it’s essential to track not just the end result, but also how your bot is managing your capital throughout the process. RoB helps answer important questions like "How much of my capital is being used at any given time?" and "Am I taking on unnecessary risk for the returns I'm getting?"

The Code

Here's the code I came up with for calculating RoB. It’s still in testing, but I think it’s pretty promising so far. It calculates total returns, daily returns, and adjusted returns, all while considering how much capital was used and for how long.

function calculateReturnOnBot(orders) {
    // Sort orders by time to ensure chronological order
    orders.sort((a, b) => a.time - b.time);

    // Initialize variables
    let positionSize = 0; // Total units held
    let capitalUtilized = 0; // Capital tied up in open positions
    let totalNetProfit = 0; // Sum of realized PnL
    let totalWeightedCapitalUtilized = 0; // Sum of (Capital Utilized * Duration)
    let totalDuration = 0; // Total time in milliseconds
    let previousTime = orders[0].time; // Time of the first order
    let maxCapitalUtilized = 0; // Maximum capital utilized

    for (let i = 0; i < orders.length; i++) {
        const order = orders[i];
        const currentTime = order.time;

        // Calculate duration since the previous order
        const duration = currentTime - previousTime;

        // Accumulate the weighted capital utilized
        totalWeightedCapitalUtilized += capitalUtilized * duration;

        // Accumulate total duration
        totalDuration += duration;

        // Update previousTime for the next iteration
        previousTime = currentTime;

        // Extract necessary fields from the order
        const amount = parseFloat(order.amount);
        const rate = parseFloat(order.rate);
        const pnl = parseFloat(order.pnl);

        if (order.type === "buy") {
            // Update position size
            positionSize += amount;

            // Update capital utilized
            capitalUtilized += amount * rate;

        } else if (order.type === "sell") {
            // Update total net profit
            totalNetProfit += pnl;

            // Update position size
            positionSize -= amount;

            // Update capital utilized
            capitalUtilized -= amount * rate;
        }

        // Ensure capitalUtilized doesn't go negative due to rounding errors
        capitalUtilized = Math.max(capitalUtilized, 0);

        // Update the maximum capital utilized
        maxCapitalUtilized = Math.max(maxCapitalUtilized, capitalUtilized);
    }

    // Handle the last time interval (assuming capital utilized remains the same after the last order)
    const endTime = orders[orders.length - 1].time;
    const finalDuration = endTime - previousTime;
    totalWeightedCapitalUtilized += capitalUtilized * finalDuration;
    totalDuration += finalDuration;

    // Calculate average capital utilized
    const averageCapitalUtilized = totalWeightedCapitalUtilized / totalDuration;

    // Convert totalDuration from milliseconds to days
    const millisecondsInDay = 24 * 60 * 60 * 1000;
    const totalDurationInDays = totalDuration / millisecondsInDay;

    // Calculate Return on Bot (RoB)
    const returnOnBot = totalNetProfit / averageCapitalUtilized;

    // Calculate daily Return on Bot as a percentage
    const dailyReturnPercentage = (returnOnBot / totalDurationInDays) * 100;

    // Calculate total return percentage over the trading period
    const totalReturnPercentage = returnOnBot * 100;

    // Adjusted Return on Bot using maximum capital utilized
    const adjustedReturnOnBot = totalNetProfit / maxCapitalUtilized;

    // Adjusted total return percentage
    const adjustedTotalReturnPercentage = adjustedReturnOnBot * 100;

    // Adjusted daily return percentage
    const adjustedDailyReturnPercentage = (adjustedReturnOnBot / totalDurationInDays) * 100;

    // Return the calculated metrics
    return {
        totalNetProfit: totalNetProfit,
        averageCapitalUtilized: averageCapitalUtilized,
        maxCapitalUtilized: maxCapitalUtilized,
        totalReturnPercentage: totalReturnPercentage.toFixed(2),
        dailyReturnPercentage: dailyReturnPercentage.toFixed(4),
        adjustedTotalReturnPercentage: adjustedTotalReturnPercentage.toFixed(2),
        adjustedDailyReturnPercentage: adjustedDailyReturnPercentage.toFixed(4),
        totalDurationInDays: totalDurationInDays.toFixed(2)
    };
}

I'd love to hear your feedback on this. Does RoB seem like something that would be useful for your trading strategies? I'm considering adding this as a feature in the next Gunbot release. Feel free to try it out and let me know what you think!

Sort:  
Loading...

Coin Marketplace

STEEM 0.15
TRX 0.16
JST 0.028
BTC 68067.18
ETH 2441.90
USDT 1.00
SBD 2.41