> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reportify.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 策略回测

> 运行量化策略回测并获取绩效分析

## 运行策略回测

执行策略回测，返回绩效指标和交易记录。

```bash theme={null}
POST /v1/quant/backtest
```

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.reportify.cn/v1/quant/backtest \
    -H "Authorization: Bearer <token>" \
    -H "Content-Type: application/json" \
    -d '{
      "start_date": "2024-01-01",
      "end_date": "2025-01-01",
      "market": "cn",
      "symbols": ["000001"],
      "entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))",
      "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))",
      "initial_cash": 100000,
      "benchmark": {
        "symbol": "000905",
        "market": "cn",
        "stock_type": "index"
      },
      "commission": 0.0003,
      "position_size": 0.2,
      "max_positions": 5,
      "min_volume": 100
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.reportify.cn/v1/quant/backtest",
      headers={"Authorization": "Bearer <token>"},
      json={
          "start_date": "2024-01-01",
          "end_date": "2025-01-01",
          "market": "cn",
          "symbols": ["000001"],
          "entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))",
          "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))",
          "initial_cash": 100000,
          "benchmark": {
              "symbol": "000905",
              "market": "cn",
              "stock_type": "index"
          },
          "commission": 0.0003,
          "position_size": 0.2,
          "max_positions": 5,
          "min_volume": 100
      }
  )
  print(response.json())
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch('https://api.reportify.cn/v1/quant/backtest', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <token>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      start_date: '2024-01-01',
      end_date: '2025-01-01',
      market: 'cn',
      symbols: ['000001'],
      entry_formula: 'CROSS(MA(CLOSE, 5), MA(CLOSE, 10))',
      exit_formula: 'CROSS(MA(CLOSE, 10), MA(CLOSE, 5))',
      initial_cash: 100000,
      benchmark: {
        symbol: '000905',
        market: 'cn',
        stock_type: 'index'
      },
      commission: 0.0003,
      position_size: 0.2,
      max_positions: 5,
      min_volume: 100
    })
  });
  const data = await response.json();
  ```
</CodeGroup>

### 请求参数

<ParamField body="start_date" type="string" required>
  回测开始日期，格式：`YYYY-MM-DD`
</ParamField>

<ParamField body="end_date" type="string" required>
  回测结束日期，格式：`YYYY-MM-DD`
</ParamField>

<ParamField body="market" type="string" default="cn">
  股票市场：`cn`（A股）, `hk`（港股）, `us`（美股）
</ParamField>

<ParamField body="symbols" type="array" default="[]">
  回测股票代码列表。如果不提供，则默认回测当前所选市场（如A股、美股或港股）。当前市场回测时建议配合 `filter_formula` 过滤不符合条件的股票。
</ParamField>

<ParamField body="filter_formula" type="string">
  股票池预筛选公式。在执行每日回测逻辑前，系统会先用此公式对当前市场的股票进行过滤，结果大于 0（即为 True）的股票才会保留在当日的可用股票池中，参与后续的行情数据加载和买卖信号计算。通常用于当前市场范围选股时过滤掉 ST 股、停牌股或不符合基本面要求的股票。

  <Expandable title="公式示例">
    * `NOT(IS_ST())` - 过滤 ST 股票
    * `(PE_TTM() > 0) & (PE_TTM() < 30)` - 过滤亏损股且要求 PE 小于 30
    * `NOT(IS_ST()) & (ROE() > 10)` - 过滤 ST 股票且要求 ROE 大于 10%
  </Expandable>
</ParamField>

<ParamField body="entry_formula" type="string">
  买入/开仓公式，结果大于 0 时触发买入（如不提供则必须提供 `strategy_code`）。支持技术指标与基本面因子。

  <Expandable title="公式示例">
    * `CROSS(MA(CLOSE, 5), MA(CLOSE, 10))` - 均线金叉买入
    * `RSI(14) < 30` - RSI 超卖买入
    * `CLOSE > BOLL(20, 2).upper` - 突破布林带上轨买入
    * `(RSI(14) < 30) & (CLOSE > MA(CLOSE, 20))` - 组合条件
    * `(PE_TTM() < 20) & (ROE() > 15)` - 基本面因子选股
  </Expandable>
</ParamField>

<ParamField body="exit_formula" type="string">
  卖出/平仓公式，结果大于 0 时触发卖出（可选）

  <Expandable title="公式示例">
    * `CROSS(MA(CLOSE, 10), MA(CLOSE, 5))` - 均线死叉卖出
    * `RSI(14) > 70` - RSI 超买卖出
    * `CLOSE < BOLL(20, 2).lower` - 跌破布林带下轨卖出
  </Expandable>
</ParamField>

<ParamField body="strategy_code" type="string">
  自定义回测策略的 Python 源码代码。若提供，将执行自定义策略而非公式策略。

  **注意：** 策略代码必须定义一个名为 `handle_data(context, datas)` 的函数作为回测引擎的入口点。
</ParamField>

<ParamField body="initial_cash" type="number" default="100000">
  初始资金（元）
</ParamField>

<ParamField body="commission" type="number" default="0">
  佣金费率，买卖通用（如 0.0003 表示万三）。若同时设置 `buy_commission` / `sell_commission`，则以后者为准
</ParamField>

<ParamField body="buy_commission" type="number" default="0">
  买入手续费率，优先于 `commission`（如 0.0003 表示万三）
</ParamField>

<ParamField body="sell_commission" type="number" default="0">
  卖出手续费率，优先于 `commission`（如 0.0013 表示万三佣金 + 千一印花税）
</ParamField>

<ParamField body="min_commission_amount" type="number" default="0">
  单笔最低手续费金额（元），如 5.0 表示每笔至少收 5 元手续费
</ParamField>

<ParamField body="slippage" type="number" default="0">
  滑点比例（如 0.001 表示千一），买入价上浮、卖出价下浮，模拟真实成交价差
</ParamField>

<ParamField body="position_size" type="number | null" default="null">
  单只股票最大仓位比例，例如 0.2 表示单只股票占用总资金的 20%。默认 `null`（不限制）
</ParamField>

<ParamField body="max_positions" type="integer | null" default="null">
  最大持仓股票数量。默认 `null`（不限制）
</ParamField>

<ParamField body="min_volume" type="integer" default="100">
  最小买入股数（如A股的 1 手即 100 股）
</ParamField>

<ParamField body="auto_close" type="boolean" default="true">
  是否在回测结束时自动平仓
</ParamField>

<ParamField body="cheat_on_open" type="boolean" default="false">
  是否在 T 日信号生成后的 T 日开盘执行交易。默认 `false` 为 T+1 开盘执行
</ParamField>

<ParamField body="signal_factors" type="object">
  预计算因子字典，用于 `strategy_code` 模式下提前计算买卖所需的指标，或在回测中返回额外的值（可选）。可通过 `factors` 接口获取可用因子列表。

  <Expandable title="signal_factors 示例">
    ```json theme={null}
    {
      "ma5": "MA(CLOSE, 5)",
      "ma10": "MA(CLOSE, 10)",
      "rsi": "RSI(14)",
      "pe": "PE_TTM()",
      "roe": "ROE()"
    }
    ```
  </Expandable>
</ParamField>

<ParamField body="benchmark" type="object">
  回测对比基准配置。`benchmark` 必须是对象，不能直接传字符串代码。

  <Expandable title="benchmark 示例">
    ```json theme={null}
    {
      "symbol": "000905",
      "market": "cn",
      "stock_type": "index"
    }
    ```

    常见用法：

    * `{"symbol": "000905", "market": "cn", "stock_type": "index"}` - 中证500
    * `{"symbol": "000300", "market": "cn", "stock_type": "index"}` - 沪深300
    * `{"symbol": "510500", "market": "cn", "stock_type": "etf"}` - ETF 基准

    错误示例：

    * `"000905"` - 错误，接口期望 object，不是 string
  </Expandable>
</ParamField>

### 响应参数

<ResponseField name="success" type="boolean">
  回测是否成功
</ResponseField>

<ResponseField name="initial_cash" type="number">
  初始资金
</ResponseField>

<ResponseField name="final_cash" type="number">
  最终资金
</ResponseField>

<ResponseField name="total_return" type="number">
  总收益（元）
</ResponseField>

<ResponseField name="total_return_pct" type="number">
  总收益率（如 0.156 表示 15.6%）
</ResponseField>

<ResponseField name="max_drawdown" type="number">
  最大回撤（如 -0.082 表示 -8.2%）
</ResponseField>

<ResponseField name="profit_factor" type="number">
  盈利因子（总盈利 / 总亏损）
</ResponseField>

<ResponseField name="win_rate" type="number">
  胜率（如 0.65 表示 65%）
</ResponseField>

<ResponseField name="total_trades" type="integer">
  总交易次数
</ResponseField>

<ResponseField name="winning_trades" type="integer">
  盈利交易次数
</ResponseField>

<ResponseField name="losing_trades" type="integer">
  亏损交易次数
</ResponseField>

<ResponseField name="trades" type="array">
  交易详情列表

  <Expandable title="Trade 字段">
    * `id`: 交易 ID
    * `symbol`: 股票代码
    * `type`: 交易类型（`Long` 或 `Short`）
    * `entry_date`: 开仓日期
    * `exit_date`: 平仓日期
    * `entry_price`: 开仓价格
    * `exit_price`: 平仓价格
    * `size`: 交易数量
    * `net_pnl`: 净盈亏
    * `return_pct`: 收益率百分比
    * `cumulative_pnl`: 累计盈亏
  </Expandable>
</ResponseField>

<ResponseField name="portfolio_value" type="object">
  每日账户净值序列，用于绘制资产走势图。键为日期，值为净值。
</ResponseField>

<ResponseField name="benchmark_value" type="object">
  基准每日净值序列（按初始资金等比例折算），用于与策略净值对比。
</ResponseField>

<ResponseField name="benchmark_return_pct" type="number">
  基准总收益率（如 0.154 表示 15.4%）
</ResponseField>

<ResponseField name="annualized_return_pct" type="number">
  年化收益率（如 0.15 表示 15%，按 252 交易日折算）
</ResponseField>

<ResponseField name="sharpe_ratio" type="number">
  夏普比率（年化，无风险利率按 0 计算）
</ResponseField>

<ResponseField name="alpha" type="number">
  Alpha（年化，CAPM Jensen's Alpha）
</ResponseField>

<ResponseField name="beta" type="number">
  Beta（策略相对基准的系统性风险暴露）
</ResponseField>

<ResponseField name="max_drawdown_start" type="string">
  最大回撤起始日期（峰值日）
</ResponseField>

<ResponseField name="max_drawdown_end" type="string">
  最大回撤结束日期（谷值日）
</ResponseField>

<ResponseField name="daily_returns" type="object">
  日收益率序列（键为日期，值为日收益率小数），用于日收益率柱状图。
</ResponseField>

<ResponseField name="drawdown_series" type="object">
  每日回撤序列（键为日期，值为回撤比例小数），用于回撤阴影图。
</ResponseField>

<ResponseField name="error_msg" type="string">
  错误信息，仅当 success 为 false 时非空
</ResponseField>

### 响应示例

```json theme={null}
{
  "success": true,
  "initial_cash": 100000,
  "commission": 0.0003,
  "final_cash": 115600,
  "total_return": 15600,
  "total_return_pct": 0.156,
  "max_drawdown": -0.082,
  "profit_factor": 2.35,
  "win_rate": 0.65,
  "total_trades": 12,
  "winning_trades": 8,
  "losing_trades": 4,
  "trades": [
    {
      "id": 1,
      "symbol": "000001",
      "type": "Long",
      "entry_date": "2024-01-15",
      "exit_date": "2024-02-20",
      "entry_price": 11.25,
      "exit_price": 12.50,
      "size": 8800,
      "net_pnl": 10937.3,
      "return_pct": 0.111,
      "cumulative_pnl": 10937.3
    }
  ],
  "portfolio_value": {
    "2024-01-15": 100000.0,
    "2024-01-16": 101200.5,
    "2024-02-20": 110937.3
  },
  "benchmark_value": {
    "2024-01-15": 100000.0,
    "2024-01-16": 100850.1,
    "2024-02-20": 108430.6
  },
  "benchmark_return_pct": 0.0843,
  "annualized_return_pct": 0.172,
  "sharpe_ratio": 1.18,
  "alpha": 0.041,
  "beta": 0.92,
  "max_drawdown_start": "2024-03-11",
  "max_drawdown_end": "2024-04-18",
  "daily_returns": {
    "2024-01-16": 0.0120,
    "2024-01-17": -0.0041
  },
  "drawdown_series": {
    "2024-03-11": 0.0000,
    "2024-04-18": 0.0820
  }
}
```

***

## 策略公式示例

### 均线金叉死叉策略

5 日均线上穿 10 日均线时买入，下穿时卖出：

```json theme={null}
{
    "entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))",
    "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))",
    "symbols": ["000001"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01"
}
```

### RSI 超买超卖策略

RSI 低于 30 时买入，高于 70 时卖出：

```json theme={null}
{
    "entry_formula": "RSI(14) < 30",
    "exit_formula": "RSI(14) > 70",
    "symbols": ["600519"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01"
}
```

### MACD 金叉死叉策略

MACD DIF 上穿 DEA 时买入，下穿时卖出：

```json theme={null}
{
    "entry_formula": "CROSS(MACD().dif, MACD().dea)",
    "exit_formula": "CROSS(MACD().dea, MACD().dif)",
    "symbols": ["000002"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01"
}
```

### 布林带突破策略

价格突破布林带上轨时买入，跌破下轨时卖出：

```json theme={null}
{
    "entry_formula": "CLOSE > BOLL(20, 2).upper",
    "exit_formula": "CLOSE < BOLL(20, 2).lower",
    "symbols": ["000001"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01"
}
```

### 组合条件策略

RSI 超卖且价格在 20 日均线上方买入，RSI 超买或价格跌破均线卖出：

```json theme={null}
{
    "entry_formula": "(RSI(14) < 30) & (CLOSE > MA(CLOSE, 20))",
    "exit_formula": "(RSI(14) > 70) | (CLOSE < MA(CLOSE, 20))",
    "symbols": ["600036"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01",
    "commission": 0.0003,
    "position_size": 0.8
}
```

### 当前市场选股与过滤策略

如果不指定 `symbols`，系统将在当前市场（由 `market` 字段决定，默认为A股 `cn`）执行回测。可以利用 `filter_formula` 在当前市场范围内进行过滤筛选，排除不满足基本面或状态要求的股票：

```json theme={null}
{
    "start_date": "2024-01-01",
    "end_date": "2025-01-01",
    "filter_formula": "NOT(IS_ST()) & (PE_TTM() < 20) & (ROE() > 15)",
    "entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 20))",
    "exit_formula": "CROSS(MA(CLOSE, 20), MA(CLOSE, 5))",
    "position_size": 0.1,
    "max_positions": 10
}
```

### 带 signal\_factors 和自定义策略的回测

使用 `signal_factors` 预计算因子并在自定义策略 `strategy_code` 中调用：

```json theme={null}
{
    "symbols": ["000001"],
    "start_date": "2024-01-01",
    "end_date": "2025-01-01",
    "signal_factors": {
        "ma5": "MA(CLOSE, 5)",
        "ma10": "MA(CLOSE, 10)",
        "rsi": "RSI(14)",
        "macd_dif": "MACD().dif",
        "pe": "PE_TTM()"
    },
    "strategy_code": "def handle_data(context, datas):\n    for data in datas:\n        symbol = data.name\n        position = context.portfolio.get_position(symbol)\n        if not position:\n            if data.ma5 > data.ma10 and data.pe < 20:\n                context.order_target_percent(symbol, 0.2)\n        elif data.rsi > 70:\n            context.order_target_percent(symbol, 0)"
}
```

***

## 参数说明

### 佣金设置

| 参数                      | 值        | 描述                   |
| ----------------------- | -------- | -------------------- |
| `commission`            | `0`      | 不计算佣金                |
| `commission`            | `0.0003` | 买卖统一万三（0.03%）        |
| `buy_commission`        | `0.0003` | 买入万三                 |
| `sell_commission`       | `0.0013` | 卖出万三佣金 + 千一印花税（A股推荐） |
| `min_commission_amount` | `5`      | 每笔最低 5 元手续费          |

### 滑点设置

| 值       | 描述                          |
| ------- | --------------------------- |
| `0`     | 不考虑滑点                       |
| `0.001` | 千一滑点（买入价上浮 0.1%，卖出价下浮 0.1%） |
| `0.002` | 千二滑点                        |

### 止损设置

| 值      | 描述     |
| ------ | ------ |
| `0`    | 不设止损   |
| `0.05` | 5% 止损  |
| `0.1`  | 10% 止损 |

### 仓位设置

| 值      | 描述                    |
| ------ | --------------------- |
| `0.99` | 使用 99% 资金（预留部分应对价格波动） |
| `0.5`  | 使用 50% 资金（半仓操作）       |
| `0.3`  | 使用 30% 资金（轻仓试探）       |

***

## 上传 Excel 文件进行回测

上传包含 OHLCV 数据的 Excel 文件进行回测，无需依赖系统内置数据源，使用自有行情数据执行策略回测。

```bash theme={null}
POST /v1/quant/backtest/upload
```

<Note>
  该接口使用 `multipart/form-data` 格式上传，不支持 JSON body。
</Note>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.reportify.cn/v1/quant/backtest/upload \
    -H "Authorization: Bearer <token>" \
    -F "file=@backtest_data.xlsx" \
    -F 'params={"entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))", "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))", "initial_cash": 100000, "commission": 0.0003}'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.reportify.cn/v1/quant/backtest/upload",
      headers={"Authorization": "Bearer <token>"},
      files={"file": open("backtest_data.xlsx", "rb")},
      data={
          "params": '{"entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))", "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))", "initial_cash": 100000, "commission": 0.0003}'
      }
  )
  print(response.json())
  ```

  ```typescript TypeScript theme={null}
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);
  formData.append('params', JSON.stringify({
    entry_formula: 'CROSS(MA(CLOSE, 5), MA(CLOSE, 10))',
    exit_formula: 'CROSS(MA(CLOSE, 10), MA(CLOSE, 5))',
    initial_cash: 100000,
    commission: 0.0003
  }));

  const response = await fetch('https://api.reportify.cn/v1/quant/backtest/upload', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer <token>' },
    body: formData
  });
  const data = await response.json();
  ```
</CodeGroup>

### Excel 文件格式要求

<ParamField body="file" type="file" required>
  Excel 文件（`.xlsx` 或 `.xls` 格式），包含回测所需的行情数据。

  **必须包含的列：**

  | 列名      | 类型 | 说明   |
  | ------- | -- | ---- |
  | `date`  | 日期 | 交易日期 |
  | `open`  | 数字 | 开盘价  |
  | `high`  | 数字 | 最高价  |
  | `low`   | 数字 | 最低价  |
  | `close` | 数字 | 收盘价  |

  **可选列：**

  | 列名       | 类型  | 说明                                  |
  | -------- | --- | ----------------------------------- |
  | `symbol` | 字符串 | 股票代码（多标的回测时必须提供，单标的时缺省为 `"UPLOAD"`） |
  | `volume` | 数字  | 成交量                                 |
  | `amount` | 数字  | 成交额                                 |

  **自定义字段：** 支持任意英文字段名（仅字母、数字、下划线，不能以数字开头），值为数字类型。例如 `pe`、`market_cap`、`pb_ratio` 等。这些字段可在公式中直接引用。

  **中文列名支持：** 系统会自动将常见的中文列名映射为对应的英文列名：

  | 中文列名                 | 映射到      |
  | -------------------- | -------- |
  | 日期 / 时间 / 交易日期 / 交易日 | `date`   |
  | 开盘 / 开盘价             | `open`   |
  | 最高 / 最高价             | `high`   |
  | 最低 / 最低价             | `low`    |
  | 收盘 / 收盘价             | `close`  |
  | 成交量 / 交易量            | `volume` |
  | 成交额 / 交易额            | `amount` |
  | 代码 / 股票代码 / 证券代码     | `symbol` |

  <Note>自定义字段列名仍须为 ASCII 字符（英文字母、数字、下划线）。</Note>
</ParamField>

### 请求参数 (params)

`params` 为表单字段，值为 JSON 字符串，支持以下参数（与标准回测接口一致，但不含 `market`/`symbols`/`filter_formula`/`start_date`/`end_date`）：

<ParamField body="entry_formula" type="string">
  买入/开仓公式，结果大于 0 时触发买入（如不提供则必须提供 `strategy_code`）
</ParamField>

<ParamField body="exit_formula" type="string">
  卖出/平仓公式，结果大于 0 时触发卖出
</ParamField>

<ParamField body="strategy_code" type="string">
  自定义回测策略的 Python 源码代码，与 `entry_formula` 互斥
</ParamField>

<ParamField body="initial_cash" type="number" default="100000">
  初始资金（元）
</ParamField>

<ParamField body="commission" type="number" default="0">
  佣金费率（如 0.0003 表示万三）
</ParamField>

<ParamField body="auto_close" type="boolean" default="true">
  是否在回测结束时自动平仓
</ParamField>

<ParamField body="signal_factors" type="object">
  指标与因子字典，用于预计算买卖信号或自定义字段

  <Expandable title="signal_factors 示例">
    ```json theme={null}
    {
      "ma5": "MA(CLOSE, 5)",
      "ma10": "MA(CLOSE, 10)",
      "rsi": "RSI(14)"
    }
    ```
  </Expandable>
</ParamField>

<ParamField body="position_size" type="number" default="0.2">
  单只股票最大仓位比例
</ParamField>

<ParamField body="max_positions" type="integer" default="5">
  最大持仓股票数量
</ParamField>

<ParamField body="min_volume" type="integer" default="100">
  最小买入股数
</ParamField>

### 响应参数

响应格式与标准回测接口完全一致，参见上方 [响应参数](#响应参数) 章节。

### Excel 上传回测示例

#### 单标的回测

Excel 文件包含单只股票数据（无需 `symbol` 列）：

| date       | open  | high  | low   | close | volume  |
| ---------- | ----- | ----- | ----- | ----- | ------- |
| 2024-01-02 | 10.50 | 10.80 | 10.40 | 10.75 | 5000000 |
| 2024-01-03 | 10.70 | 10.90 | 10.60 | 10.85 | 4500000 |

```json theme={null}
{
  "entry_formula": "CROSS(MA(CLOSE, 5), MA(CLOSE, 10))",
  "exit_formula": "CROSS(MA(CLOSE, 10), MA(CLOSE, 5))",
  "initial_cash": 100000,
  "commission": 0.0003
}
```

#### 多标的回测

Excel 文件包含多只股票数据（必须有 `symbol` 列）：

| date       | symbol | open  | high  | low   | close | volume  |
| ---------- | ------ | ----- | ----- | ----- | ----- | ------- |
| 2024-01-02 | 000001 | 10.50 | 10.80 | 10.40 | 10.75 | 5000000 |
| 2024-01-02 | 600519 | 1800  | 1815  | 1790  | 1810  | 2000000 |

```json theme={null}
{
  "entry_formula": "RSI(14) < 30",
  "exit_formula": "RSI(14) > 70",
  "position_size": 0.3,
  "max_positions": 2
}
```

#### 带自定义字段的回测

Excel 文件包含自定义基本面字段（如 `pe`、`pb`）：

| date       | symbol | open  | high  | low   | close | volume  | pe   | pb  |
| ---------- | ------ | ----- | ----- | ----- | ----- | ------- | ---- | --- |
| 2024-01-02 | 000001 | 10.50 | 10.80 | 10.40 | 10.75 | 5000000 | 15.2 | 1.3 |

可在公式中直接引用自定义字段名：

```json theme={null}
{
  "entry_formula": "(CLOSE > MA(CLOSE, 20)) & (pe < 20)",
  "exit_formula": "CLOSE < MA(CLOSE, 20)",
  "initial_cash": 100000
}
```

***

## 注意事项

<Note>
  * 回测结果仅供参考，历史收益不代表未来表现
  * 可通过 `slippage` 参数模拟滑点，`buy_commission` / `sell_commission` 分别设置买卖手续费以更贴近真实交易成本
  * 建议使用合理的佣金和止损参数以更接近真实交易
  * 如果不设置 `exit_formula`，则只有买入信号，卖出依赖止损或 `auto_close`
</Note>


## OpenAPI

````yaml POST /v1/quant/backtest
openapi: 3.1.0
info:
  title: Reportify API
  version: 1.0.0
  description: API documentation for Reportify's document management and search services.
servers:
  - url: https://api.reportify.cn
    description: Production server
security:
  - BearerAuth: []
paths:
  /v1/quant/backtest:
    post:
      tags:
        - openapi-quant
      summary: Run strategy backtest
      description: >
        Execute strategy backtest with the given parameters.


        **Variables vs Functions:**

        - Variables (no parentheses): `CLOSE`, `OPEN`, `HIGH`, `LOW`, `VOLUME`,
        `AMOUNT`

        - Functions (with parentheses): `MA(CLOSE, 20)`, `RSI(14)`, `PE()`,
        `ROE()`, etc.


        **Input Parameters:**

        - `start_date`: Backtest start date (required)

        - `end_date`: Backtest end date (required)

        - `market`: Stock market (cn, hk, us), default: cn

        - `symbols`: List of stock codes (optional if filter_formula is
        provided)

        - `filter_formula`: Pre-filter formula, e.g., 'NOT(IS_ST)'

        - `entry_formula`: Buy/entry formula, triggers buy when result > 0
        (required if strategy_code is not provided)

        - `exit_formula`: Sell/exit formula, triggers sell when result > 0
        (optional)

        - `strategy_code`: Custom backtest strategy Python code (optional)

        - `initial_cash`: Initial capital, default: 100000.0

        - `commission`: Commission rate, default: 0.0

        - `position_size`: Max position size ratio per stock, default: 0.2

        - `max_positions`: Max number of holding stocks, default: 5

        - `min_volume`: Minimum trading volume, default: 100

        - `auto_close`: Auto close position at end, default: true

        - `indicator`: Indicator dictionary for custom strategy pre-computation
        or returning values


        **Formula Examples:**

        - `CROSS(MA(CLOSE, 5), MA(CLOSE, 20))` - Golden cross signal

        - `RSI(14) < 30` - RSI oversold

        - `MA(CLOSE, 5) > MA(CLOSE, 20)` - State-based uptrend

        - `CLOSE > REF(CLOSE, 1) * 1.05` - Up more than 5%

        - `(PE() < 20) & (ROE() > 0.1)` - Fundamental screening


        **Output:**

        Returns backtest results including:

        - Performance metrics (return, drawdown, win rate, etc.)

        - Trade list with entry/exit details

        - Daily portfolio values
      operationId: quant_backtest
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BacktestInput'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BacktestOutput'
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - BearerAuth: []
components:
  schemas:
    BacktestInput:
      properties:
        start_date:
          type: string
          format: date
          title: Start Date
          description: Backtest start date (required)
        end_date:
          type: string
          format: date
          title: End Date
          description: Backtest end date (required)
        market:
          $ref: '#/components/schemas/StockMarket'
          description: Stock market (cn, hk, us), default cn
          default: cn
        symbols:
          anyOf:
            - type: array
              items:
                type: string
            - type: 'null'
          title: Symbols
          description: >-
            List of stock codes. If empty, defaults to full market (must provide
            filter_formula)
        filter_formula:
          anyOf:
            - type: string
            - type: 'null'
          title: Filter Formula
          description: Pre-filter formula, e.g., 'NOT(IS_ST)'
        entry_formula:
          anyOf:
            - type: string
            - type: 'null'
          title: Entry Formula
          description: Buy/entry formula, triggers buy when result > 0
        exit_formula:
          anyOf:
            - type: string
            - type: 'null'
          title: Exit Formula
          description: Sell/exit formula, triggers sell when result > 0 (optional)
        strategy_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Strategy Code
          description: Backtest strategy python code
        initial_cash:
          type: number
          title: Initial Cash
          description: Initial capital, default 100000.0
          default: 100000
        commission:
          type: number
          title: Commission
          description: Commission rate, default 0.0
          default: 0
        buy_commission:
          type: number
          title: Buy Commission
          description: >-
            Buy commission rate, takes priority over commission (e.g., 0.0003
            for 0.03%)
          default: 0
        sell_commission:
          type: number
          title: Sell Commission
          description: >-
            Sell commission rate, takes priority over commission (e.g., 0.0013
            for A-share sell including stamp duty)
          default: 0
        min_commission_amount:
          type: number
          title: Min Commission Amount
          description: >-
            Minimum commission per trade in CNY (e.g., 5.0 means at least 5 yuan
            per trade)
          default: 0
        slippage:
          type: number
          title: Slippage
          description: Slippage ratio (e.g., 0.001 for 0.1%, buy price up, sell price down)
          default: 0
        auto_close:
          type: boolean
          title: Auto Close
          description: Auto close position at end, default true
          default: true
        signal_factors:
          anyOf:
            - type: object
              additionalProperties: true
            - type: 'null'
          title: Signal Factors
          description: Signal factors dictionary for custom strategy pre-computation
        position_size:
          type: number
          title: Position Size
          description: Max position size ratio per stock, default 0.2
          default: 0.2
        max_positions:
          type: integer
          title: Max Positions
          description: Max number of holding stocks, default 5
          default: 5
        min_volume:
          type: integer
          title: Min Volume
          description: Minimum trading volume (e.g., 100 for A-shares), default 100
          default: 100
      type: object
      required:
        - start_date
        - end_date
      title: BacktestInput
      description: Backtest input parameters for strategy execution.
    BacktestOutput:
      type: object
      properties:
        success:
          type: boolean
          title: Success
          description: Whether backtest completed successfully
          default: true
        initial_cash:
          type: number
          title: Initial Cash
          description: Initial capital
          default: 100000
        commission:
          type: number
          title: Commission
          description: Commission rate
          default: 0
        final_cash:
          type: number
          title: Final Cash
          description: Final capital after backtest
          default: 100000
        total_return:
          type: number
          title: Total Return
          description: Total profit/loss amount
          default: 0
        total_return_pct:
          type: number
          title: Total Return Pct
          description: Total return percentage
          default: 0
        max_drawdown:
          type: number
          title: Max Drawdown
          description: Maximum drawdown percentage
          default: 0
        profit_factor:
          type: number
          title: Profit Factor
          description: Gross profit / Gross loss ratio
          default: 0
        win_rate:
          type: number
          title: Win Rate
          description: Winning trades percentage
          default: 0
        total_trades:
          type: integer
          title: Total Trades
          description: Total number of completed trades
          default: 0
        winning_trades:
          type: integer
          title: Winning Trades
          description: Number of profitable trades
          default: 0
        losing_trades:
          type: integer
          title: Losing Trades
          description: Number of losing trades
          default: 0
        trades:
          type: array
          title: Trades
          description: List of trade details
          items:
            $ref: '#/components/schemas/TradeItem'
          default: []
        portfolio_value:
          type: object
          additionalProperties:
            type: number
          title: Portfolio Value
          description: Daily portfolio values (for equity curve)
          default: {}
        benchmark_value:
          type: object
          additionalProperties:
            type: number
          title: Benchmark Value
          description: Daily benchmark values scaled to initial capital
          default: {}
        benchmark_return_pct:
          type: number
          title: Benchmark Return Pct
          description: Benchmark total return percentage
          default: 0
        sharpe_ratio:
          type: number
          title: Sharpe Ratio
          description: Annualized Sharpe ratio with risk-free rate = 0
          default: 0
        alpha:
          type: number
          title: Alpha
          description: Annualized CAPM Jensen's Alpha with risk-free rate = 0
          default: 0
        beta:
          type: number
          title: Beta
          description: Strategy beta relative to benchmark
          default: 0
        max_drawdown_start:
          anyOf:
            - type: string
            - type: 'null'
          title: Max Drawdown Start
          description: Start date of maximum drawdown period (peak date)
        max_drawdown_end:
          anyOf:
            - type: string
            - type: 'null'
          title: Max Drawdown End
          description: End date of maximum drawdown period (trough date)
        daily_returns:
          type: object
          additionalProperties:
            type: number
          title: Daily Returns
          description: Daily return series (decimal values)
          default: {}
        drawdown_series:
          type: object
          additionalProperties:
            type: number
          title: Drawdown Series
          description: Daily drawdown series (positive decimal values)
          default: {}
        error_msg:
          anyOf:
            - type: string
            - type: 'null'
          title: Error Msg
          description: Error message when success is false
      title: BacktestOutput
      description: Backtest result containing performance metrics and trade details.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    StockMarket:
      type: string
      enum:
        - cn
        - hk
        - us
        - global
      title: StockMarket
      description: Stock market identifier
    TradeItem:
      type: object
      required:
        - id
        - type
        - entry_date
        - exit_date
        - entry_price
        - exit_price
        - size
        - net_pnl
        - return_pct
        - cumulative_pnl
      properties:
        id:
          type: integer
          title: Id
          description: Trade ID
        symbol:
          anyOf:
            - type: string
            - type: 'null'
          title: Symbol
          description: Stock code (optional for multi-symbol backtest)
        type:
          type: string
          title: Type
          description: Trade type, "Long" for long position, "Short" for short position
        entry_date:
          type: string
          title: Entry Date
          description: Entry date (YYYY-MM-DD)
        exit_date:
          type: string
          title: Exit Date
          description: Exit date (YYYY-MM-DD)
        entry_price:
          type: number
          title: Entry Price
          description: Entry price
        exit_price:
          type: number
          title: Exit Price
          description: Exit price
        size:
          type: integer
          title: Size
          description: Trade size (number of shares)
        net_pnl:
          type: number
          title: Net Pnl
          description: Net profit/loss
        return_pct:
          type: number
          title: Return Pct
          description: Return percentage
        cumulative_pnl:
          type: number
          title: Cumulative Pnl
          description: Cumulative profit/loss after this trade
      title: TradeItem
      description: Single trade details from entry to exit.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Enter your Bearer token

````