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

# 串关与 SGP - 构建投注单

> OddsPapi 多关投注的工作流指南：如何在 parlay 与 SGP 端点之间选择、如何让实时投注单保持正确报价、如何横向比较博彩公司，以及某一关被暂停时如何优雅降级。

[串关与 SGP](/zh/api-reference/parlays) 是这两个多关端点逐字段的参考文档。
本指南负责另一半内容：**如何把它们接入一个在用户仍在编辑时也能保持正确的投注单。**

***

## 该用哪个端点

这个选择由各关自身决定，而不是由偏好决定。

<Steps>
  <Step title="所有关都在同一场赛事内？">
    使用 `GET /fixtures/odds/sgp`。由博彩公司定价，因此 `price` 体现了各关之间真实的
    相关性——"大 2.5 球"和"主队获胜"并不是独立事件，简单相乘会高估这张单子。
  </Step>

  <Step title="各关跨多场赛事？">
    使用 `GET /fixtures/odds/parlay`。各关相互独立，因此价格就是各欧赔的乘积，
    在本地即时算出。
  </Step>

  <Step title="两者混合？">
    `/sgp` 会拒绝——所有关必须属于同一场赛事。要么拆分投注单，
    要么用 `/parlay` 整体定价并接受这个不含相关性的数字。
  </Step>
</Steps>

同样两关，两种答案并排对比：

<Tabs>
  <Tab title="/parlay——简单相乘">
    ```json theme={null}
    "parlay": {
      "bet365": {
        "id1400003160574217:bet365:141:0,id1400003160574217:bet365:146:0": {
          "bookmaker": "bet365",
          "active": true,
          "price": 7.98,
          "singlesPrice": 7.98,
          "changedAt": 1766667441097
        }
      }
    }
    ```
  </Tab>

  <Tab title="/sgp——博彩公司报价">
    ```json theme={null}
    "sgp": {
      "bet365": {
        "id1400003160574217:bet365:141:0,id1400003160574217:bet365:146:0": {
          "bookmaker": "bet365",
          "active": true,
          "price": 6.5,
          "singlesPrice": 7.98,
          "changedAt": 1766667441097,
          "betslip": "https://www.bet365.com/dl/sportsbookredirect?bs=..."
        }
      }
    }
    ```
  </Tab>
</Tabs>

同样的关、同样的 `parlayId`，两个不同的价格。`singlesPrice` 在两边都是简单乘积；
在 `/sgp` 上，它与 `price` 之间的差值就是相关性加成。
把两个数字同时展示出来，才能让用户看懂一张 SGP。

***

## 横向比较博彩公司

各关按**博彩公司**分组，且 `parlayId` 在两个端点上以相同方式构建
（排序、去重后的 `oddsIds` 以 `,` 连接）。由此可以直接利用两点：

* 在一次调用中对多家博彩公司请求同一组选择，就能在同一个 `parlayId` 下
  并排拿到每家的报价。
* 对同一组选择而言，`/parlay` 的结果与 `/sgp` 的结果可以直接比较——
  键相同，定价模型不同。

无法为该投注单定价的博彩公司会直接不出现在该部分中。缺席并不是错误，详见下文。

***

## 让实时投注单保持报价

投注单是一个长期存在的对象，而价格会在它下面持续变动。

* **每次增减关卡都重新定价。** 选择一改变，`parlayId` 就会改变，
  因此缓存的价格天然就以正确的键存放。
* **按固定节奏重新定价，而不是每收到一个 tick 就调用。** 两个端点的上限都是
  **每秒 10 次请求**。对实时投注单请按固定间隔轮询，而不要追着每一次赔率更新跑——
  `/sgp` 的调用可能会往返博彩公司，因此即便配额相同，它也是更慢的那一个。
* **最多 20 关。** 超出时两个端点都会拒绝。

<Warning>
  不要对 `/parlay` 并行发起语言遍历或博彩公司遍历。每秒 10 次是按密钥计的，
  而该端点响应足够快，以至于一次突发会在您察觉之前就触发限流——
  其症状看起来像是空的 parlay 部分，而不像限流错误。
</Warning>

***

## 优雅降级

有三种不同的情况会导致一张投注单无法定价，好的界面应当加以区分：

| 发生了什么    | 您看到的现象                                      | 该如何告知用户           |
| -------- | ------------------------------------------- | ----------------- |
| 某一关从未被找到 | 该 `oddsId` 出现在 `missingOddsIds` 中           | 该选择无效——请移除        |
| 某一关暂时关闭  | 该关仍然存在但为 inactive，并带有 `meta.inactiveReason` | 已暂停——重新开放后投注单即可恢复 |
| 博彩公司无法报价 | 该博彩公司不出现在 `sgp` 中，且**没有** `missingOddsIds`  | 换一家博彩公司试试         |

第三行最容易让人意外：我们这边所有关都找到了，但博彩公司自己的定价服务
无法解析这张串关。于是该部分为空，同时也没有任何内容被报告为缺失——
因为确实没有任何东西缺失。完整的 `inactiveReason` 清单参见
[暂停与缺失的各关](/zh/api-reference/parlays#suspended-vs-missing-legs)。

`odds` 部分不会替您过滤——inactive 的关会被刻意保留返回，
这样您就可以在投注单上原地渲染一个已暂停的关，而不是让它凭空消失。

***

## 周期与各关

同一场赛事中来自不同周期的关可以正常组合——一个 `fulltime` 1X2 和一条 `p1` 总分线
和其他任何关没有区别。如果您正在构建供用户挑选的盘口分组，请先阅读
[各项目的周期](/zh/guides/periods)：某个运动项目是否提供 `fulltime`
取决于它的结构，而想当然地认为一定提供，是出现空盘口分组最常见的原因。

***

## 相关页面

<Columns cols={2}>
  <Card title="串关与 SGP 参考" icon="layer-group" href="/zh/api-reference/parlays">
    全部字段、错误与 `inactiveReason`。
  </Card>

  <Card title="速率限制" icon="gauge-high" href="/zh/api-reference/rate-limits">
    各端点的权威配额。
  </Card>

  <Card title="各项目的周期" icon="clock" href="/zh/guides/periods">
    哪些周期存在于哪些项目，以及原因。
  </Card>

  <Card title="打造体育博彩产品" icon="store" href="/zh/guides/sportsbook">
    这张投注单所处的完整链路。
  </Card>
</Columns>
