Signal Backtester

MEDIUM-HARD • Live C++ Rust Java Python
500K
ROWS
7
METRICS
3
SIGNAL TYPES

Problem Description

Backtest a trading signal against historical price data. Each row contains a timestamp, price, and signal value (-1 for sell, 0 for flat, 1 for buy). Execute trades based on signal changes and compute performance metrics.

Compute total P&L, number of trades, win rate, maximum drawdown, Sharpe ratio, Sortino ratio, and maximum consecutive wins. Output 7 aggregate values -- 5 floats and 2 integers.

Tier System & Performance Targets

LANGUAGEGOLDSILVERBRONZE
C++ / Rust< 300ms< 1000ms< 5000ms
Java< 600ms< 2000ms< 10000ms
Python< 3000ms< 10000ms< 45000ms

Evaluation Criteria

Correctness: Your program outputs 7 values. 5 float values are compared with tolerance 0.01, and 2 integer values must match exactly. All 7 must be correct to pass.

Performance: Wall-clock time to process all rows determines tier placement.

Input Format

Read from stdin. The first line is the number of rows N. The next N lines each contain a comma-separated row:

timestamp,price,signal

Where:

Output Format

Output exactly 7 lines to stdout:

TOTAL_PNL
NUM_TRADES
WIN_RATE
MAX_DRAWDOWN
SHARPE_RATIO
SORTINO_RATIO
MAX_CONSECUTIVE_WINS

Where:

Example

Input

8
1000,100.00,0
1001,101.50,1
1002,103.00,1
1003,102.00,-1
1004,99.50,-1
1005,100.25,0
1006,98.00,1
1007,101.00,0

Output

4.500000
3
0.666667
0.025000
1.250000
1.850000
2

Line 1: Total P&L from all trades. Line 2: 3 round-trip trades (integer). Line 3: 2 of 3 trades were winners. Line 4: Max drawdown. Line 5-6: Sharpe and Sortino ratios. Line 7: Longest winning streak (integer).

Submission Rules

Starter Templates

C++
#include <cstdio>
#include <cmath>
#include <vector>

int main() {
    int N;
    scanf("%d", &N);

    long long ts;
    double price;
    int signal;

    double total_pnl = 0;
    int num_trades = 0, max_consec_wins = 0;
    // Track trades, returns, drawdown...

    for (int i = 0; i < N; i++) {
        scanf("%lld,%lf,%d", &ts, &price, &signal);

        // Implement: execute trades on signal changes
        // Track P&L, wins/losses, drawdown, returns for Sharpe/Sortino
    }

    double win_rate = 0, max_dd = 0, sharpe = 0, sortino = 0;
    // Calculate final metrics

    printf("%.6f\n", total_pnl);
    printf("%d\n", num_trades);
    printf("%.6f\n", win_rate);
    printf("%.6f\n", max_dd);
    printf("%.6f\n", sharpe);
    printf("%.6f\n", sortino);
    printf("%d\n", max_consec_wins);
    return 0;
}
Python
import sys
import math

N = int(input())

total_pnl = 0.0
num_trades = 0
wins = 0
max_consec_wins = 0
consec_wins = 0
max_drawdown = 0.0
returns = []

prev_signal = 0
entry_price = 0.0

for _ in range(N):
    parts = input().split(',')
    ts = int(parts[0])
    price = float(parts[1])
    signal = int(parts[2])

    # Implement: execute trades on signal changes
    # Track P&L, wins/losses, drawdown, returns for Sharpe/Sortino

    prev_signal = signal

win_rate = wins / num_trades if num_trades > 0 else 0.0
# Calculate Sharpe and Sortino from returns
sharpe = 0.0
sortino = 0.0

print(f"{total_pnl:.6f}")
print(num_trades)
print(f"{win_rate:.6f}")
print(f"{max_drawdown:.6f}")
print(f"{sharpe:.6f}")
print(f"{sortino:.6f}")
print(max_consec_wins)
Rust
use std::io::{self, BufRead, Write, BufWriter};

fn main() {
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut out = BufWriter::new(stdout.lock());
    let mut lines = stdin.lock().lines();

    let n: usize = lines.next().unwrap().unwrap().trim().parse().unwrap();

    let mut total_pnl: f64 = 0.0;
    let mut num_trades: i32 = 0;
    let mut max_consec_wins: i32 = 0;
    // Track trades, returns, drawdown...

    for _ in 0..n {
        let line = lines.next().unwrap().unwrap();
        let parts: Vec<&str> = line.trim().split(',').collect();
        let _ts: i64 = parts[0].parse().unwrap();
        let price: f64 = parts[1].parse().unwrap();
        let signal: i32 = parts[2].parse().unwrap();

        // Implement: execute trades on signal changes
    }

    let win_rate: f64 = 0.0;
    let max_dd: f64 = 0.0;
    let sharpe: f64 = 0.0;
    let sortino: f64 = 0.0;

    writeln!(out, "{:.6}", total_pnl).unwrap();
    writeln!(out, "{}", num_trades).unwrap();
    writeln!(out, "{:.6}", win_rate).unwrap();
    writeln!(out, "{:.6}", max_dd).unwrap();
    writeln!(out, "{:.6}", sharpe).unwrap();
    writeln!(out, "{:.6}", sortino).unwrap();
    writeln!(out, "{}", max_consec_wins).unwrap();
}
Java
import java.util.*;
import java.io.*;

public class Solution {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine().trim());

        double totalPnl = 0;
        int numTrades = 0, maxConsecWins = 0;
        // Track trades, returns, drawdown...

        for (int i = 0; i < N; i++) {
            String[] parts = br.readLine().trim().split(",");
            long ts = Long.parseLong(parts[0]);
            double price = Double.parseDouble(parts[1]);
            int signal = Integer.parseInt(parts[2]);

            // Implement: execute trades on signal changes
        }

        double winRate = 0, maxDd = 0, sharpe = 0, sortino = 0;

        System.out.printf("%.6f%n", totalPnl);
        System.out.printf("%d%n", numTrades);
        System.out.printf("%.6f%n", winRate);
        System.out.printf("%.6f%n", maxDd);
        System.out.printf("%.6f%n", sharpe);
        System.out.printf("%.6f%n", sortino);
        System.out.printf("%d%n", maxConsecWins);
    }
}

Submit Your Solution

Supported formats: .cpp, .py, .rs, .java, or raw text