Northstar v9.0.0 已经发布,盈富量化平台本次更新的重点集中在交易量、K 线周期、行情数据接口和模型抽象几个基础层面。对量化策略开发者来说,最直接的变化是交易量不再被限制为整数,这让平台更适合数字货币等允许分数数量的交易场景。
小数交易量解决了什么问题
v8 版本只能接受整数交易量,而币圈交易通常允许按小数下单。例如,现货交易可能使用 0.001 BTC,某些代币则可能使用更多小数位。如果交易系统只能接收整数,策略层就需要额外做缩放、取整或换算,容易带来三类问题:
- 订单数量与策略计算结果不一致;
- 取整后产生残余资金或仓位偏差;
- 不同交易所适配时,需要在平台外重复处理数量精度。
v9 版本接受小数交易量后,策略可以更自然地表达目标仓位和下单数量。不过,支持小数并不等于可以忽略交易所规则。实际接入时仍应检查最小下单量、数量步长、价格精度和账户可用余额,并在提交订单前进行统一校验。
可以这样实践一个最小的数量校验器。示例使用 Python 标准库 Decimal,避免二进制浮点数带来的精度误差:
from decimal import Decimal, InvalidOperation
def normalize_quantity(raw: str, step: str, minimum: str) -> Decimal:
"""按交易量步长截断数量,并检查最小下单量。"""
try:
quantity = Decimal(raw)
step_size = Decimal(step)
min_quantity = Decimal(minimum)
except InvalidOperation as exc:
raise ValueError("quantity, step and minimum must be valid decimals") from exc
if quantity <= 0 or step_size <= 0:
raise ValueError("quantity and step must be greater than zero")
normalized = (quantity // step_size) * step_size
if normalized < min_quantity:
raise ValueError(f"quantity {normalized} is below minimum {min_quantity}")
return normalized
if __name__ == "__main__":
quantity = normalize_quantity("0.123456", "0.001", "0.002")
print(quantity) # 0.123
这段代码可以放在策略订单和交易接口之间,具体的 step 与 minimum 应来自目标交易平台的交易规则,而不是写死在策略中。
K 线周期改为固定枚举
摘要显示,v9 将 K 线周期按照行业最佳实践固定为枚举项。相比自由传入字符串,枚举周期能让调用方和数据源对周期名称形成更稳定的约定,也能减少拼写差异带来的运行时错误。
例如,业务代码可以把策略支持的周期限制在明确集合内:
from enum import Enum
class BarInterval(str, Enum):
MINUTE_1 = "1m"
MINUTE_5 = "5m"
MINUTE_15 = "15m"
HOUR_1 = "1h"
DAY_1 = "1d"
def load_bars(symbol: str, interval: BarInterval, limit: int = 200) -> None:
print(f"load {limit} bars: symbol={symbol}, interval={interval.value}")
if __name__ == "__main__":
load_bars("BTCUSDT", BarInterval.MINUTE_15)
改造已有策略时,建议把原先散落的 "15m"、"15min" 或 "15分钟" 统一收敛到一个周期枚举。这样做还便于在数据源适配层集中完成格式转换:策略使用平台枚举,交易所适配器再转换为目标接口所需要的周期字段。
IDataSource 更贴近币圈行情接口
v9 同时优化了 IDataSource 接口,使其设计逻辑更接近币圈行情接口。这个方向的价值在于,策略层不需要了解每个行情平台的请求细节,数据源适配器可以负责处理交易对格式、K 线周期、分页、时间范围和返回字段映射。
可以按下面的方式组织一个简化的数据源抽象。这里是实践示例,具体方法名和参数应以 Northstar v9 的实际接口定义为准:
from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime
@dataclass(frozen=True)
class Bar:
timestamp: datetime
open: float
high: float
low: float
close: float
volume: float
class IDataSource(ABC):
@abstractmethod
def get_bars(self, symbol: str, interval: str, limit: int = 200) -> list[Bar]:
raise NotImplementedError
class DemoCryptoDataSource(IDataSource):
def get_bars(self, symbol: str, interval: str, limit: int = 200) -> list[Bar]:
# 实际项目中,这里替换为交易所 HTTP API 调用和字段映射。
print(f"request symbol={symbol}, interval={interval}, limit={limit}")
return []
if __name__ == "__main__":
source = DemoCryptoDataSource()
source.get_bars("BTCUSDT", "15m", 100)
落地时可以把数据源划分为三层:
- 策略层只依赖标准化后的行情对象和周期枚举;
IDataSource负责稳定的调用契约;- 具体适配器负责币种符号、请求参数、鉴权、限流和响应解析。
这样,替换行情平台时,变化主要集中在适配器内部,不会扩散到指标计算和交易策略。
模型抽象优化带来的影响
摘要还提到模型抽象进一步优化,但没有给出完整的 API 变更清单。因此,升级时不宜仅凭版本号推断所有模型类都可以直接替换。更稳妥的做法是检查 v9 的接口定义和迁移说明,重点确认:
- 模型基类或公共接口是否发生变化;
- 构造函数参数和默认值是否调整;
- 历史数据、实时数据和交易信号之间的类型是否统一;
- 自定义模型需要实现的方法是否增加或改名;
- 序列化、回测结果和实盘执行之间是否仍保持兼容。
如果项目中有自定义策略模型,建议先用一组固定行情样本做回归测试,再切换生产环境。回归测试至少应比较信号数量、下单数量、持仓变化和最终收益,尤其要覆盖小数交易量场景。
升级时可以按这个顺序检查
Northstar v9.0.0 的改动涉及基础接口,升级工作不应只停留在修改版本号。可以按以下顺序执行:
- 盘点项目中所有整数交易量假设,包括订单模型、数据库字段、日志格式和风控规则;
- 将价格和数量计算从二进制浮点数迁移到适合业务精度的表示方式;
- 用 K 线周期枚举替换自由字符串,并集中处理外部平台的周期映射;
- 检查
IDataSource的实现类和模拟数据源,确认方法签名与返回数据结构; - 用历史行情执行回测,对比 v8 与 v9 的信号和订单结果;
- 在仿真或小额环境验证最小下单量、数量步长和余额校验;
- 确认模型抽象相关的迁移要求后,再切换实盘流量。
总体来看,v9.0.0 的方向是让平台的基础能力更贴近数字货币交易:交易量表达更自然,K 线周期更规范,行情数据接口也更接近实际市场 API。升级收益主要体现在减少适配层的重复逻辑,但数量精度、交易所规则和模型兼容性仍需要由应用方通过测试和风控流程兜底。