mirror of
https://ghfast.top/https://github.com/aeroxw/easy_tdx_max.git
synced 2026-09-12 16:54:20 +08:00
docs: add backtest engine design spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
626d0aae44
commit
8d68e9c094
@@ -321,4 +321,14 @@ def BIAS_SIGNAL(CLOSE, P=10, M=30): #乖离率信号指标:M日乖离 + 短/
|
||||
X_LMA = MA(X, M) #长周期信号线 MA(X,M)
|
||||
return RD(X), RD(S_SMA), RD(X_LMA)
|
||||
|
||||
def FK(CLOSE): #FK趋势指标:快线EMA(2)与斜率外推慢线EMA(42)比较
|
||||
fast = EMA(CLOSE, 2)
|
||||
slow = EMA(SLOPE(CLOSE, 21) * 20 + CLOSE, 42)
|
||||
return fast > slow
|
||||
|
||||
def OUTPERFORM_20D(CLOSE, INDEX_CLOSE): #20日相对强度:个股涨幅跑赢大盘返回1,否则返回0
|
||||
stock_ret = (CLOSE - REF(CLOSE, 20)) / REF(CLOSE, 20)
|
||||
index_ret = (INDEX_CLOSE - REF(INDEX_CLOSE, 20)) / REF(INDEX_CLOSE, 20)
|
||||
return IF(stock_ret > index_ret, 1, 0)
|
||||
|
||||
#望大家能提交更多指标和函数 https://github.com/mpquant/MyTT
|
||||
|
||||
+14
-10
@@ -1,12 +1,16 @@
|
||||
"""响应帧头解析与 zlib 解压。
|
||||
|
||||
响应帧格式(16 字节固定头 + body):
|
||||
struct "<IIIHH"
|
||||
偏移 0: I (4字节) — 未知
|
||||
偏移 4: I (4字节) — 未知
|
||||
偏移 8: I (4字节) — 未知
|
||||
响应帧格式(16 字节固定头 + body),字节级结构(gotdx 交叉验证):
|
||||
偏移 0: I (4字节) — magic = 7654321 (0x0074CBB1),协议标识
|
||||
偏移 4: B (1字节) — ZipFlag:bit4=1 表示 body 已压缩,0x0C=未压缩, 0x1C=已压缩
|
||||
偏移 5: I (4字节) — SeqID:请求 bytes 1-4 的回显(命令标识)
|
||||
偏移 9: B (1字节) — 保留(观察到恒为 0x00)
|
||||
偏移 10: H (2字节) — Method:请求 bytes 10-11 的回显
|
||||
偏移 12: H (2字节) — zipsize(body 实际长度)
|
||||
偏移 14: H (2字节) — unzipsize(解压后长度;等于 zipsize 表示未压缩)
|
||||
|
||||
兼容说明:使用 IIIHH 解码可正确提取 zipsize/unzipsize。前三个 uint32 中:
|
||||
u0 = magic, u1 = ZipFlag(1B) + SeqID(3B 低字节), u2 = SeqID(1B 高字节) + 保留(1B) + Method(2B)
|
||||
"""
|
||||
|
||||
import zlib
|
||||
@@ -21,22 +25,22 @@ _HEADER_FMT = "<IIIHH"
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FrameHeader:
|
||||
unknown_0: int
|
||||
unknown_1: int
|
||||
unknown_2: int
|
||||
magic: int # 协议魔数,恒为 7654321
|
||||
seq_id: int # ZipFlag(1B) + 请求 bytes 1-4 回显(3B)
|
||||
method: int # 请求回显(1B) + 保留(1B) + Method(2B)
|
||||
zipsize: int
|
||||
unzipsize: int
|
||||
|
||||
|
||||
def parse_header(buf: bytes) -> FrameHeader:
|
||||
"""解析 16 字节响应帧头。"""
|
||||
u0, u1, u2, zipsize, unzipsize = unpack_from(
|
||||
magic, seq_id, method, zipsize, unzipsize = unpack_from(
|
||||
_HEADER_FMT,
|
||||
buf,
|
||||
0,
|
||||
"frame header",
|
||||
)
|
||||
return FrameHeader(u0, u1, u2, zipsize, unzipsize)
|
||||
return FrameHeader(magic, seq_id, method, zipsize, unzipsize)
|
||||
|
||||
|
||||
def decompress_body(header: FrameHeader, raw_body: bytes) -> bytes:
|
||||
|
||||
@@ -39,10 +39,10 @@ class GetSecurityListCmd(BaseCommand[list[SecurityInfo]]):
|
||||
code_bytes,
|
||||
volunit,
|
||||
name_bytes,
|
||||
_unknown1, # 4字节,含义未明
|
||||
_unknown1, # 4字节,排序/分组字段(非用户可见数据)
|
||||
decimal_point,
|
||||
pre_close_raw,
|
||||
_unknown2, # 4字节,含义未明
|
||||
_unknown2, # 4字节,私有时间戳(非用户可见数据)
|
||||
) = struct.unpack("<6sH8s4sBI4s", raw)
|
||||
|
||||
code = code_bytes.decode("utf-8", errors="replace").rstrip("\x00")
|
||||
|
||||
@@ -100,8 +100,8 @@ class GetSecurityQuotesCmd(BaseCommand[list[SecurityQuote]]):
|
||||
s_vol, pos = get_price(body, pos)
|
||||
b_vol, pos = get_price(body, pos)
|
||||
|
||||
unknown_2, pos = get_price(body, pos)
|
||||
unknown_3, pos = get_price(body, pos)
|
||||
unknown_2, pos = get_price(body, pos) # IndexOpenAmount(指数)/舍入残差(个股)
|
||||
unknown_3, pos = get_price(body, pos) # StockOpenAmount(个股)/负值(指数)
|
||||
|
||||
# 五档买盘
|
||||
bid1_d, pos = get_price(body, pos)
|
||||
@@ -129,8 +129,8 @@ class GetSecurityQuotesCmd(BaseCommand[list[SecurityQuote]]):
|
||||
bv5, pos = get_price(body, pos)
|
||||
av5, pos = get_price(body, pos)
|
||||
|
||||
# 尾部:2字节 H + 4个 get_price + 2字节 h + 2字节 H
|
||||
(unknown_4,) = unpack_from("<H", body, pos, "security_quotes tail flag")
|
||||
# 尾部:2字节 H(交易状态标志,0x8020=停牌)+ 4个 get_price + 2字节 h + 2字节 H
|
||||
(trading_status,) = unpack_from("<H", body, pos, "security_quotes tail flag")
|
||||
pos += 2
|
||||
unknown_5, pos = get_price(body, pos)
|
||||
unknown_6, pos = get_price(body, pos)
|
||||
@@ -196,6 +196,8 @@ class GetSecurityQuotesCmd(BaseCommand[list[SecurityQuote]]):
|
||||
unknown_7=unknown_7,
|
||||
unknown_8=unknown_8,
|
||||
server_time=_format_server_time(unknown_0),
|
||||
trading_status=trading_status,
|
||||
open_amount=unknown_3 * 100.0,
|
||||
_raw=body[record_start:pos],
|
||||
)
|
||||
)
|
||||
|
||||
@@ -9,7 +9,10 @@ from .enums import Market
|
||||
class SecurityQuote:
|
||||
"""单只股票实时五档行情。
|
||||
|
||||
带 unknown_ 前缀的字段为协议中尚未明确含义的字段,保留以供逆向分析。
|
||||
带 unknown_ 前缀的字段保留原始协议值,其含义已在逆向分析中确认:
|
||||
unknown_2: 指数→集合竞价成交金额/100;个股→舍入残差≈0
|
||||
unknown_3: 个股→集合竞价成交金额/100;指数→负值/无意义
|
||||
unknown_5-8: 保留字段,恒为 0
|
||||
_raw 为该股票记录的原始字节切片。
|
||||
"""
|
||||
|
||||
@@ -17,18 +20,18 @@ class SecurityQuote:
|
||||
code: str
|
||||
|
||||
# 价格
|
||||
price: float # 现价
|
||||
price: float # 现价
|
||||
pre_close: float # 昨收
|
||||
open: float # 今开
|
||||
high: float # 最高
|
||||
low: float # 最低
|
||||
open: float # 今开
|
||||
high: float # 最高
|
||||
low: float # 最低
|
||||
|
||||
# 量额
|
||||
vol: float # 总成交量(手)
|
||||
cur_vol: float # 当前成交量
|
||||
amount: float # 成交额(元)
|
||||
s_vol: float # 内盘(主动卖)
|
||||
b_vol: float # 外盘(主动买)
|
||||
vol: float # 总成交量(手)
|
||||
cur_vol: float # 当前成交量
|
||||
amount: float # 成交额(元)
|
||||
s_vol: float # 内盘(主动卖)
|
||||
b_vol: float # 外盘(主动买)
|
||||
|
||||
# 活跃度指标(含义来自社区逆向,仅供参考)
|
||||
active1: int
|
||||
@@ -60,21 +63,25 @@ class SecurityQuote:
|
||||
|
||||
# 价格指标
|
||||
rise_speed: float # 涨速(原 reversed_bytes9 / 100)
|
||||
limit_up: float | None # 涨停价(业务规则计算)
|
||||
limit_up: float | None # 涨停价(业务规则计算)
|
||||
limit_down: float | None # 跌停价(业务规则计算)
|
||||
|
||||
# 未知字段:买卖量之后的两个变长整数(保留供进一步分析)
|
||||
unknown_2: int = field(default=0, repr=False) # 未知变长整数 2
|
||||
unknown_3: int = field(default=0, repr=False) # 未知变长整数 3
|
||||
# 协议原始值(含义已确认,保留以供高级分析)
|
||||
unknown_2: int = field(default=0, repr=False) # 指数: IndexOpenAmount/100; 个股: 舍入残差
|
||||
unknown_3: int = field(default=0, repr=False) # 个股: StockOpenAmount/100; 指数: 负值
|
||||
|
||||
# 未知字段:尾部四个变长整数
|
||||
unknown_5: int = field(default=0, repr=False) # 原 reversed_bytes5
|
||||
unknown_6: int = field(default=0, repr=False) # 原 reversed_bytes6
|
||||
unknown_7: int = field(default=0, repr=False) # 原 reversed_bytes7
|
||||
unknown_8: int = field(default=0, repr=False) # 原 reversed_bytes8
|
||||
# 尾部保留字段
|
||||
unknown_5: int = field(default=0, repr=False) # 保留,恒为 0
|
||||
unknown_6: int = field(default=0, repr=False) # 保留,恒为 0
|
||||
unknown_7: int = field(default=0, repr=False) # 保留,恒为 0
|
||||
unknown_8: int = field(default=0, repr=False) # 保留,恒为 0
|
||||
|
||||
# 服务器时间字符串(从 unknown_0 原始整数解析,格式 HH:MM:SS.mmm)
|
||||
server_time: str = field(default="", repr=True)
|
||||
|
||||
# 已确认语义的新字段
|
||||
trading_status: int = field(default=0, repr=False) # 交易状态标志,0x8020=停牌
|
||||
open_amount: float = field(default=0.0, repr=False) # 集合竞价成交金额(元),个股有效
|
||||
|
||||
# 原始字节(该股票记录切片)
|
||||
_raw: bytes = field(default=b"", repr=False, compare=False)
|
||||
|
||||
Reference in New Issue
Block a user