Skip to content

策略报告

运行策略脚本后,Navi 会生成一份 StrategyReport,包含性能指标、交易历史、权益曲线和配置详情。

报告结构

StrategyReportinstance.strategy_report() 返回的顶层类型:

rust
pub struct StrategyReport {
    /// 策略配置快照(初始资金、手续费等)
    pub config: StrategyConfigReport,
    /// 所有交易的综合性能指标
    pub performance_all: PerformanceMetrics,
    /// 仅多头交易的性能指标
    pub performance_long: PerformanceMetrics,
    /// 仅空头交易的性能指标
    pub performance_short: PerformanceMetrics,
    /// 已平仓交易列表(按平仓时间排序)
    pub closed_trades: Vec<ClosedTradeReport>,
    /// 当前未平仓(浮动盈亏)的交易
    pub open_trades: Vec<OpenTradeReport>,
    /// 每根 K 线的权益值(索引 0 = 第一根 K 线)
    pub equity_curve: Vec<f64>,
    /// 每根 K 线相对峰值权益的回撤(始终 ≥ 0)
    pub drawdown_curve: Vec<f64>,
    /// 每根 K 线的买入持有权益(initial_capital × close / first_close)
    pub buy_hold_curve: Vec<f64>,
    /// 用于计算 Sharpe/Sortino 的日回报率序列
    pub daily_returns: Vec<DailyReturnReport>,
    /// 从首次入场到最后一笔平仓的时间范围(无已平仓交易时为 None)
    pub trading_range: Option<TradingRangeReport>,
}

策略配置

StrategyConfigReport 记录了策略在 strategy() 中声明的参数:

字段类型说明
initial_capitalf64初始账户资金
commission_typeCommissionTypePerContractPerTradePercentOfValue
commission_valuef64对应手续费类型的手续费金额
margin_longf64多头保证金要求(%)
margin_shortf64空头保证金要求(%)
slippagef64订单滑点(以 tick 为单位)
pyramidingu32同方向最大同时入场次数
risk_free_ratef64用于 Sharpe/Sortino 的年化无风险利率(%)
process_orders_on_closebool在当根 K 线收盘而非次根开盘时成交订单
calc_on_order_fillsbool每笔订单成交后重新执行脚本
close_entries_ruleCloseEntriesRuleFifoAny

性能指标

PerformanceMetrics 分三种维度计算:所有交易(performance_all)、仅多头(performance_long)、仅空头(performance_short)。

以下字段仅在 performance_all 中有意义 — 它们基于整体权益曲线,无法按方向拆分。在 performance_longperformance_short 中这些字段固定为 0.0None

  • max_drawdown / max_drawdown_percent
  • max_runup / max_runup_percent
  • buy_hold_return / buy_hold_return_percent
  • sharpe_ratio / sortino_ratio
  • num_even_trades

盈亏

字段说明
net_profit以账户货币计的净利润
net_profit_percent净利润占初始资金的百分比
gross_profit获利交易的利润总和
gross_profit_percent总利润百分比
gross_loss亏损交易的亏损总和(正数)
gross_loss_percent总亏损百分比
profit_factor总利润 ÷ 总亏损(无亏损交易时为 None
buy_hold_return买入持有的收益(账户货币,仅 performance_all
buy_hold_return_percent买入持有收益百分比(仅 performance_all

回撤与上升

仅在 performance_all 中有值,在 performance_long / performance_short 中始终为 0.0

字段说明
max_drawdown最大权益回撤(账户货币)
max_drawdown_percent最大回撤百分比
max_runup最大权益上升(账户货币)
max_runup_percent最大上升百分比

风险调整收益

仅在 performance_all 中有值,在 performance_long / performance_short 中始终为 None

字段说明
sharpe_ratio年化 Sharpe 比率(数据不足时为 None
sortino_ratio年化 Sortino 比率(数据不足时为 None

交易统计

字段说明
total_closed_trades已完成的交易总数
total_open_trades回测结束时未平仓的交易数
num_winning_trades盈利(profit > 0)的交易数
num_losing_trades亏损(profit < 0)的交易数
num_even_trades平本(profit == 0)的交易数(仅 performance_all,其余始终为 0
percent_profitable获利交易数 ÷ 总交易数 × 100(无已平仓交易时为 None

平均交易

字段说明
avg_trade每笔交易的平均盈亏
avg_trade_percent每笔交易的平均盈亏百分比
avg_winning_trade获利交易的平均利润
avg_winning_trade_percent获利交易平均利润百分比
avg_losing_trade亏损交易的平均亏损
avg_losing_trade_percent亏损交易平均亏损百分比
ratio_avg_win_loss平均获利 ÷ 平均亏损(无亏损交易时为 None
largest_winning_trade单笔最大利润
largest_winning_trade_percent单笔最大利润百分比
largest_losing_trade单笔最大亏损
largest_losing_trade_percent单笔最大亏损百分比

持仓时间

字段说明
avg_bars_in_trades所有交易的平均持仓 K 线数
avg_bars_in_winning_trades获利交易的平均持仓 K 线数
avg_bars_in_losing_trades亏损交易的平均持仓 K 线数

其他

字段说明
commission_paid已支付的手续费总额
max_contracts_held同时持仓的最大合约/股数
margin_calls触发的追缴保证金次数

交易历史

已平仓交易

report.closed_trades 中每条 ClosedTradeReport 对应一笔已完成的交易:

字段类型说明
trade_numusize交易编号(从 0 开始)
entry_idString入场订单 ID(如 "Long Entry"
entry_commentString入场订单备注
entry_sideDirectionLongShort
entry_pricef64入场成交价
entry_barusize入场成交的 K 线索引
entry_timei64入场时间戳(Unix 毫秒)
exit_idString出场订单 ID
exit_commentString出场订单备注
exit_pricef64出场成交价
exit_barusize出场成交的 K 线索引
exit_timei64出场时间戳(Unix 毫秒)
quantityf64交易数量(合约/股数)
profitf64已实现盈亏(扣除手续费)
profit_percentf64已实现盈亏百分比(相对入场价值)
cumulative_profitf64累计盈亏(含本笔交易)
cumulative_profit_percentf64累计盈亏百分比(相对初始资金)
max_runupf64最大顺向波动(账户货币)
max_runup_percentf64最大顺向波动百分比
max_drawdownf64最大逆向波动(账户货币)
max_drawdown_percentf64最大逆向波动百分比
commissionf64本笔交易的手续费总额(入场 + 出场)

未平仓交易

report.open_trades 中每条 OpenTradeReport 对应一个未结仓位:

字段类型说明
trade_numusize交易编号(从 0 开始)
entry_idString入场订单 ID
entry_commentString入场订单备注
entry_sideDirectionLongShort
entry_pricef64入场成交价
entry_barusize入场成交的 K 线索引
entry_timei64入场时间戳(Unix 毫秒)
quantityf64持仓数量(合约/股数)
profitf64当前浮动盈亏(扣除入场手续费)
profit_percentf64当前浮动盈亏百分比
max_runupf64迄今最大浮动盈利
max_runup_percentf64迄今最大浮动盈利百分比
max_drawdownf64迄今最大浮动亏损
max_drawdown_percentf64迄今最大浮动亏损百分比
commissionf64已支付的入场手续费

权益曲线

三组 Vec<f64> 均以 K 线为索引(索引 0 = 第一根 K 线):

字段说明
equity_curve每根 K 线收盘时的账户权益
drawdown_curve每根 K 线相对峰值权益的回撤(peak - equity,始终 ≥ 0)
buy_hold_curve每根 K 线的买入持有假设权益
rust
// 找到最大回撤发生的 K 线
if let Some((bar, dd)) = report.drawdown_curve
    .iter()
    .enumerate()
    .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap())
{
    println!("最大回撤发生在第 {} 根 K 线:{:.2}", bar, dd);
}

日回报率

report.daily_returns 提供用于 Sharpe/Sortino 计算的逐日回报序列:

rust
pub struct DailyReturnReport {
    pub date: String,           // "YYYY-MM-DD"
    pub return_percent: f64,    // 当日净盈亏百分比
}

交易时间范围

report.trading_range 在至少有一笔已平仓交易时为 Some,涵盖从首次入场到最后一笔平仓的时间段:

rust
pub struct TradingRangeReport {
    pub start_time: i64,  // Unix 毫秒
    pub end_time: i64,    // Unix 毫秒
}

完整示例

rust
use navi_vm::{Candlestick, Instance, TimeFrame};

async fn backtest(candles: Vec<Candlestick>) -> Result<(), navi_vm::Error> {
    let source = r#"
strategy("均线交叉策略",
    initial_capital = 10000,
    commission_type = strategy.commission.percent,
    commission_value = 0.1)

fast = ta.sma(close, 14)
slow = ta.sma(close, 28)

if ta.crossover(fast, slow)
    strategy.entry("Long", strategy.long)
if ta.crossunder(fast, slow)
    strategy.entry("Short", strategy.short)
"#;

    let tf = TimeFrame::days(1);
    let symbol = "NASDAQ:AAPL";
    let instance = Instance::builder(candles, source, tf, symbol)
        .build().await?
        .run_to_end(symbol, tf).await?;

    let report = instance.strategy_report();
    let p = &report.performance_all;

    println!("=== 策略报告 ===");
    println!("净利润:       {:.2}({:.2}%)", p.net_profit, p.net_profit_percent);
    println!("最大回撤:     {:.2}({:.2}%)", p.max_drawdown, p.max_drawdown_percent);
    println!("盈亏比:       {:.2}", p.profit_factor.unwrap_or(0.0));
    println!("Sharpe 比率:  {:.2}", p.sharpe_ratio.unwrap_or(0.0));
    println!("总交易次数:   {}", p.total_closed_trades);
    println!("胜率:         {:.1}%", p.percent_profitable.unwrap_or(0.0));
    println!("总手续费:     {:.2}", p.commission_paid);

    println!("\n=== 交易明细 ===");
    for trade in &report.closed_trades {
        println!(
            "#{:3}  {:5}  入场={:.2}  出场={:.2}  盈亏={:.2}({:.2}%)",
            trade.trade_num,
            if trade.entry_side == navi_vm::Direction::Long { "多头" } else { "空头" },
            trade.entry_price,
            trade.exit_price,
            trade.profit,
            trade.profit_percent,
        );
    }

    Ok(())
}

下一步

基于 MIT 许可证发布。