Explore more topics
NexusTrade guide

Backtest a cryptocurrency strategy

Run saved crypto rules with fixed dates, SPY and BTC benchmarks, declared fees and detailed events.

As of 2026-10-10

Jump to a section

Read the completed BTC test before reproducing it

Strategy return
56.61%
Maximum drawdown
28.77%
SPY return
25.30%
BTC return
119.27%

Portfolio value (USD)

BTC 50-day trend: completed 2024 backtest with SPY and BTC buy and hold$25.3K$8.9KLargest decline in plotted observations: 28.77%, 2024-03-13, 20:00:00 UTC to 2024-10-11, 13:30:00 UTC2024-01-012024-12-31
BTC 50-day trend 2024-12-31, 21:00:00 UTC
$15,660.69
SPY buy and hold 2024-12-31, 21:00:00 UTC
$12,530.29
BTC buy and hold 2024-12-31, 21:00:00 UTC
$21,926.92

BTC 50-day trend: 28.77% largest decline in plotted observations. 2024-03-13, 20:00:00 UTC ($14,803.09) to 2024-10-11, 13:30:00 UTC ($10,544.26).

BTC 50-day trendSPY buy and holdBTC buy and holdHistorical simulation

This saved algorithm completed a Day backtest from 2024-01-01 through 2024-12-31, with $10000.00 starting capital. The chart includes all 744 exported history points.

Compare the strategy with SPY and BTC buy and hold. Each benchmark invests the full $10000.00 starting balance over the same 2024 period. SPY follows its trading sessions; BTC includes weekends. This algorithm follows its own allocation and entry/exit rules, with 0.7% of traded notional charged on each fill. Explore cash and position values to see how capital was deployed.

Connect the curve to one recorded signal

At 2024-10-11T13:30:00.000Z, the recorded rule was: BTC-USD last price > 50 Day BTC-USD SMA and Position market value (BTC-USD) = Constant 0. Its overall result was true. Read the individual comparisons below, then ask Aurora to explain how they led to the action.

The signal requested 95 percent of buying power at a submitted price of 61,420.7109. 1 captured Filled order shares this timestamp; Aurora receives those fields with the signal.

Scroll sideways to compare all columns. Select a heading to sort.

BTC-USD price > BTC-USD 50 day SMA61,420.7109>60,767.4145True
BTC-USD position value = constant0=0True

Set the test inputs

The examples use January 1 through December 31, 2024, $10,000 starting capital, interval Day, and SPY and BTC buy-and-hold chart comparisons. They charge 0.7% of notional on every Cryptocurrency fill. Save the rules and inputs with the result.

InputBTC example
Dates2024-01-01 through 2024-12-31
Initial value$10,000
IntervalDay
Baseline Asset SymbolBTC-USD
Baseline Asset TypeCrypto
Cryptocurrency fee0.7% of traded notional per fill

Choose the baseline in the backtest builder

In the native backtest builder, set Baseline Asset Symbol to the full pair, such as BTC-USD, and Baseline Asset Type to Crypto. Use SPY with Baseline Asset Type Stock for the stock-market comparison. The strategy pages plot both SPY and BTC over the same dates. Request detailed events to inspect signals and orders. Event capture costs 5 times the usual research tokens and the events remain available for 3 days. Review the displayed cost before submitting.

Plan a separate variant and later test

Review the optional next experiment

Keep one changed variant separate from the original. After the development comparison, freeze a chosen version before selecting a later period that has not influenced its rules.

  1. Create one variant, then test unseen dates

    Ask: "Change only the entry allocation from 95% to 75% of buying power. Show the rule diff and compare both candidates on the 2024 development period with every other setting fixed." After choosing, freeze the rules and select another test period you have not inspected. The displayed 2024 results already make 2024 a viewed development period. Keep any later revisions in a new research cycle.

Create and backtest with Python

Use the Python SDK route

Python SDK 1.42.0. Save the runner below as run_btc_trend_following.py.

Install and download

Shell
python3 -m pip install nexustrade==1.42.0
export NEXUSTRADE_API_KEY="YOUR_API_KEY"
curl --fail --output btc_trend_following.py https://nexustrade.io/seo/strategy-examples/btc-trend-following.py

Create, test and inspect

Python
from btc_trend_following import create_btc_trend_following, backtest_btc_trend_following

book = create_btc_trend_following()
completed = backtest_btc_trend_following()
print(completed["result"])

Run

Shell
python3 run_btc_trend_following.py

Python strategy and backtest functions

View complete Python SDK functions

The backtest function submits the 2024 test with SPY as its benchmark, records events and waits for the result. Use a new request key when changing rules, dates or fees.

Python
import nexustrade as nt


def create_btc_trend_following():
    asset = nt.crypto_asset("BTC-USD")
    return nt.portfolio(
        "Public SEO crypto example - BTC 50-day trend",
        [
            nt.strategy(
                "Enter BTC 50-day trend",
                ((nt.Price(asset) > nt.SMA(asset, 50, "Day")) & (nt.PositionValue(asset) == nt.Value(0))),
                nt.buy(asset, 95, "percent of buying power")
            ),
            nt.strategy(
                "Exit BTC 50-day trend",
                ((nt.Price(asset) <= nt.SMA(asset, 50, "Day")) & (nt.PositionValue(asset) > nt.Value(0))),
                nt.sell(asset, 100, "percent of current positions")
            ),
        ],
        initial_value=10000,
        supports_crypto=True,
        supports_fractional_shares=True,
        alerts_enabled=False,
        dividend_policy='cash',
    )


def backtest_btc_trend_following(client=None):
    client = client or nt.NexusTradeClient.from_environment()
    operation = client.create_backtest(
        nt.backtest(
            create_btc_trend_following(),
            start_date="2024-01-01", end_date="2024-12-31",
            interval="Day", baseline_symbol="SPY",
            initial_value=10000, generate_events=True,
            dividend_policy="cash",
            fee_config={"Stock": {"type": "percent", "amount": 0.1},
                        "Cryptocurrency": {"type": "percent", "amount": 0.7},
                        "Option": {"type": "dollars", "amount": 0.65}},
        ),
        idempotency_key="explore-btc-trend-following-2024-spy-v1",
    )
    return client.wait_for_backtest(operation["id"])


# Build locally: book = create_btc_trend_following()
# Run and inspect: completed = backtest_btc_trend_following(); print(completed["result"])

Create and backtest with TypeScript

Use the TypeScript SDK route

TypeScript SDK 1.42.0. Save the runner below as run-btc-trend-following.ts.

Install and download

Shell
npm install nexustrade@1.42.0
npm install --save-dev tsx
export NEXUSTRADE_API_KEY="YOUR_API_KEY"
curl --fail --output btc-trend-following.ts https://nexustrade.io/seo/strategy-examples/btc-trend-following.ts

Create, test and inspect

TypeScript
import { createBtcTrendFollowing, backtestBtcTrendFollowing } from "./btc-trend-following";

async function main() {
  const book = createBtcTrendFollowing();
  const completed = await backtestBtcTrendFollowing();
  console.log(completed.result);
}

main().catch((error: unknown) => {
  console.error(error);
  process.exitCode = 1;
});

Run

Shell
npx tsx run-btc-trend-following.ts

TypeScript strategy and backtest functions

View complete TypeScript SDK functions

The same rules, dates and fees are used in both SDKs. The backtest function keeps its request key across retries.

TypeScript
import * as nt from "nexustrade";

export function createBtcTrendFollowing() {
  const asset = nt.cryptoAsset("BTC-USD");
  return nt.portfolio(
    "Public SEO crypto example - BTC 50-day trend",
    [
      nt.strategy(
          "Enter BTC 50-day trend",
          nt.and(
              nt.gt(nt.Price(asset), nt.SMA(asset, 50, "Day")),
              nt.eq(nt.PositionValue(asset), nt.Value(0))
          ),
          nt.buy(asset, 95, "percent of buying power")
      ),
      nt.strategy(
          "Exit BTC 50-day trend",
          nt.and(
              nt.lte(nt.Price(asset), nt.SMA(asset, 50, "Day")),
              nt.gt(nt.PositionValue(asset), nt.Value(0))
          ),
          nt.sell(asset, 100, "percent of current positions")
      ),
    ],
    { initialValue: 10000, supportsCrypto: true, supportsFractionalShares: true, alertsEnabled: false, dividendPolicy: "cash" }
  );
}

export async function backtestBtcTrendFollowing(client = new nt.NexusTradeClient()) {
  const operation = await client.createBacktest(
    nt.backtest(createBtcTrendFollowing(), {
      startDate: "2024-01-01", endDate: "2024-12-31",
      interval: "Day", baselineSymbol: "SPY",
      initialValue: 10000, generateEvents: true,
      dividendPolicy: "cash",
      feeConfig: {
        Stock: { type: "percent", amount: 0.1 },
        Cryptocurrency: { type: "percent", amount: 0.7 },
        Option: { type: "dollars", amount: 0.65 },
      },
    }),
    { idempotencyKey: "explore-btc-trend-following-2024-spy-v1" }
  );
  if (typeof operation.id !== "string") throw new Error("Missing backtest ID");
  return client.waitForBacktest(operation.id);
}

// Build locally: const book = createBtcTrendFollowing();
// Run and inspect: const completed = await backtestBtcTrendFollowing(); console.log(completed.result);

Explore the completed result

When the run is COMPLETE, open its full history and trade events. Compare return, drawdown, fees, cash and position values with the SPY and BTC buy-and-hold curves. Keep the saved result when changing a rule or testing a new period.

Continue exploring

Discussion

Sign in or create a free account to join the discussion.

No comments yet.

Aurora · AI research assistant

Try this in Aurora

Edit the request, then open it in Aurora. You choose when to send it.