diff --git a/scripts/__init__.py b/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/probe_unknowns.py b/scripts/probe_unknowns.py new file mode 100644 index 0000000..8ef9b6d --- /dev/null +++ b/scripts/probe_unknowns.py @@ -0,0 +1,189 @@ +"""未知字段探测脚本:通过批量拉取多只股票数据,尝试推断各 unknown_N 字段的含义。 + +用法: + cd /home/m/xmtdx + python3 scripts/probe_unknowns.py + +输出: + 1. MinuteBar.unknown_1 vs 分钟均价(累计成交额 / 累计成交量) + 2. SecurityQuote.unknown_2/3/5/6/7/8 与已知行情指标的相关关系 +""" +from __future__ import annotations + +import sys +import pathlib + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent / "src")) + +from xmtdx import TdxClient, Market, KlineCategory + +HOST = "180.153.18.170" + +# 沪深各取若干活跃股票 +SH_CODES = ["600000", "600036", "601318", "600519", "601628"] +SZ_CODES = ["000001", "000002", "000858", "002415", "300750"] + +SEP = "-" * 72 + + +# --------------------------------------------------------------------------- +# Part 1: MinuteBar.unknown_1 — 是否为分钟均价? +# --------------------------------------------------------------------------- + +def probe_minute_unknown_1(c: TdxClient) -> None: + print(SEP) + print("Part 1: MinuteBar.unknown_1 vs 分钟均价 (历史某日)") + print(SEP) + + # 使用历史分时,数据确定(不随时间变化) + DATE = 20250108 + code, market = "600000", Market.SH + + bars = c.get_history_minute_time_data(market, code, DATE) + print(f" {market.name} {code} 日期={DATE} 共 {len(bars)} 条分时\n") + + # 同时拉取当日日线 K 作为参考(含 amount/vol 可算均价) + # 分时数据无直接成交额,需要用 price × vol 近似 + # 若 unknown_1 == round(price × 100) 则为原始价格单位均价 + print(f" {'分钟':>6} {'price':>8} {'vol':>8} {'unknown_1':>12} {'price*100':>10} {'diff':>8}") + print(f" {'':-<6} {'':-<8} {'':-<8} {'':-<12} {'':-<10} {'':-<8}") + + exact_match = 0 + close_match = 0 + + for i, b in enumerate(bars[:30]): # 只打印前30条 + price_x100 = round(b.price * 100) + diff = b.unknown_1 - price_x100 + exact = b.unknown_1 == price_x100 + close = abs(diff) <= 2 + + if exact: + exact_match += 1 + if close: + close_match += 1 + + flag = " <<< exact" if exact else (" ≈" if close else "") + print(f" {i+1:>6} {b.price:>8.2f} {b.vol:>8} {b.unknown_1:>12} {price_x100:>10} {diff:>+8}{flag}") + + # Count across all bars + all_exact = sum(1 for b in bars if b.unknown_1 == round(b.price * 100)) + all_close = sum(1 for b in bars if abs(b.unknown_1 - round(b.price * 100)) <= 2) + + print(f"\n 全部 {len(bars)} 条:") + print(f" unknown_1 == price*100 (精确): {all_exact}/{len(bars)} ({100*all_exact/len(bars):.1f}%)") + print(f" unknown_1 ≈ price*100 (±2): {all_close}/{len(bars)} ({100*all_close/len(bars):.1f}%)") + + # Try another hypothesis: unknown_1 is a cumulative average price (均价) + # Compute running avg: sum(price*vol)/sum(vol) + print(f"\n 另一假设:unknown_1 = 当日累计均价×100") + cum_pv = 0.0 + cum_v = 0 + correct_avg = 0 + for b in bars: + cum_pv += b.price * b.vol + cum_v += b.vol + if cum_v > 0: + avg = cum_pv / cum_v + expected = round(avg * 100) + if abs(b.unknown_1 - expected) <= 2: + correct_avg += 1 + + print(f" unknown_1 ≈ 累计均价×100 (±2): {correct_avg}/{len(bars)} ({100*correct_avg/len(bars):.1f}%)") + + +# --------------------------------------------------------------------------- +# Part 2: SecurityQuote.unknown_N fields +# --------------------------------------------------------------------------- + +def probe_quote_unknowns(c: TdxClient) -> None: + print(f"\n{SEP}") + print("Part 2: SecurityQuote.unknown_2/3/5/6/7/8 — 与已知字段的关系") + print(SEP) + + pairs = [(Market.SH, code) for code in SH_CODES] + [(Market.SZ, code) for code in SZ_CODES] + quotes = c.get_security_quotes(pairs) + + print(f" {'market':>6} {'code':>8} {'pre_close':>10} {'price':>8} " + f"{'u2':>6} {'u3':>8} {'u5':>6} {'u6':>6} {'u7':>6} {'u8':>6} {'rise_spd':>10}") + print(f" {'':-<6} {'':-<8} {'':-<10} {'':-<8} " + f"{'':-<6} {'':-<8} {'':-<6} {'':-<6} {'':-<6} {'':-<6} {'':-<10}") + + for q in quotes: + pct = (q.price - q.pre_close) / q.pre_close * 100 if q.pre_close else 0 + print( + f" {q.market.name:>6} {q.code:>8} {q.pre_close:>10.2f} {q.price:>8.2f} " + f"{q.unknown_2:>6} {q.unknown_3:>8} {q.unknown_5:>6} " + f"{q.unknown_6:>6} {q.unknown_7:>6} {q.unknown_8:>6} {q.rise_speed:>10.4f}" + ) + + print(f"\n 注:rise_speed = reversed_bytes9/100(已确认 = 涨速)") + + # Hypothesis: unknown_3 might relate to 涨停/跌停 price + # 涨停 = pre_close * 1.10 (rounded to 2 decimal) + print(f"\n 假设 unknown_3 = 涨停价×100:") + print(f" {'code':>8} {'涨停价×100 预期':>16} {'unknown_3':>10} {'diff':>6}") + for q in quotes: + if q.pre_close > 0: + limit_up = round(q.pre_close * 1.10 * 100) + diff = q.unknown_3 - limit_up + print(f" {q.code:>8} {limit_up:>16} {q.unknown_3:>10} {diff:>+6}") + + print(f"\n 假设 unknown_3 = 跌停价×100:") + print(f" {'code':>8} {'跌停价×100 预期':>16} {'unknown_3':>10} {'diff':>6}") + for q in quotes: + if q.pre_close > 0: + limit_dn = round(q.pre_close * 0.90 * 100) + diff = q.unknown_3 - limit_dn + print(f" {q.code:>8} {limit_dn:>16} {q.unknown_3:>10} {diff:>+6}") + + # unknown_2: often -1 or small value — check if it's 换手率×10000 or similar + print(f"\n unknown_2 raw values: {[q.unknown_2 for q in quotes]}") + print(f" unknown_5 raw values: {[q.unknown_5 for q in quotes]}") + print(f" unknown_6 raw values: {[q.unknown_6 for q in quotes]}") + print(f" unknown_7 raw values: {[q.unknown_7 for q in quotes]}") + print(f" unknown_8 raw values: {[q.unknown_8 for q in quotes]}") + + # Print raw bytes for manual inspection + print(f"\n 原始字节(前20字节 hex):") + for q in quotes: + print(f" {q.code}: {q._raw[:20].hex()}") + + +# --------------------------------------------------------------------------- +# Part 3: TransactionRecord.unknown_last — 是否为秒数? +# --------------------------------------------------------------------------- + +def probe_transaction_unknown_last(c: TdxClient) -> None: + print(f"\n{SEP}") + print("Part 3: TransactionRecord.unknown_last — 是否为秒或序号?") + print(SEP) + + recs = c.get_history_transaction_data(Market.SH, "600000", 20250108, 0, 30) + print(f" {'序号':>4} {'时间':>6} {'price':>8} {'vol':>6} {'buy':>4} {'unknown_last':>14}") + print(f" {'':-<4} {'':-<6} {'':-<8} {'':-<6} {'':-<4} {'':-<14}") + + for i, r in enumerate(recs): + print(f" {i+1:>4} {r.hour:02d}:{r.minute:02d} {r.price:>8.2f} {r.vol:>6} {r.buyorsell:>4} {r.unknown_last:>14}") + + unique = len({r.unknown_last for r in recs}) + print(f"\n unknown_last 唯一值数量: {unique}/{len(recs)}") + print(f" 值分布: {sorted({r.unknown_last for r in recs})}") + + +# --------------------------------------------------------------------------- +# main +# --------------------------------------------------------------------------- + +def main() -> None: + print(f"连接 {HOST}:7709 ...") + with TdxClient(HOST) as c: + probe_minute_unknown_1(c) + probe_quote_unknowns(c) + probe_transaction_unknown_last(c) + + print(f"\n{SEP}") + print("探测完成。根据以上输出可判断各字段含义,更新 models/ 文档注释。") + + +if __name__ == "__main__": + main() diff --git a/src/xmtdx/__init__.py b/src/xmtdx/__init__.py index a984ba8..d34dbbd 100644 --- a/src/xmtdx/__init__.py +++ b/src/xmtdx/__init__.py @@ -22,6 +22,7 @@ asyncio 版本:: from .client import AsyncTdxClient, TdxClient from .exceptions import TdxCommandError, TdxConnectionError, TdxDecodeError, TdxError +from .transport.sync import KNOWN_HOSTS, ping_all from .models import ( XDXR_CATEGORY_NAMES, CompanyInfoCategory, @@ -58,6 +59,9 @@ __all__ = [ "TdxConnectionError", "TdxDecodeError", "TdxCommandError", + # 工具 + "ping_all", + "KNOWN_HOSTS", ] __version__ = "0.1.0" diff --git a/src/xmtdx/client.py b/src/xmtdx/client.py index a6a620b..b10fb28 100644 --- a/src/xmtdx/client.py +++ b/src/xmtdx/client.py @@ -1,7 +1,9 @@ """高层行情 API:TdxClient(同步)和 AsyncTdxClient(asyncio)。""" from types import TracebackType +from typing import TypeVar +from .commands.base import BaseCommand from .commands.company_info import GetCompanyInfoCategoryCmd, GetCompanyInfoContentCmd from .commands.finance_info import GetFinanceInfoCmd from .commands.minute_time import GetHistoryMinuteTimeDataCmd, GetMinuteTimeDataCmd @@ -11,6 +13,7 @@ from .commands.security_list import GetSecurityListCmd from .commands.security_quotes import GetSecurityQuotesCmd from .commands.transaction import GetHistoryTransactionDataCmd, GetTransactionDataCmd from .commands.xdxr_info import GetXdxrInfoCmd +from .exceptions import TdxConnectionError from .models.bar import SecurityBar from .models.enums import KlineCategory, Market from .models.finance import CompanyInfoCategory, FinanceInfo, XdxrRecord @@ -18,10 +21,10 @@ from .models.quote import SecurityQuote from .models.security import SecurityInfo from .models.timeseries import MinuteBar, TransactionRecord from .transport.async_ import AsyncTdxConnection -from .transport.sync import TdxConnection +from .transport.sync import KNOWN_HOSTS, TdxConnection, ping_all -_DEFAULT_HOST = "180.153.18.170" _DEFAULT_PORT = 7709 +_T = TypeVar("_T") # ============================================================ @@ -30,22 +33,66 @@ _DEFAULT_PORT = 7709 class TdxClient: - """同步通达信行情客户端。 + """同步通达信行情客户端,支持 IP 优选与断线自动重连。 使用示例:: + # 单台服务器 with TdxClient("180.153.18.170") as c: bars = c.get_security_bars(Market.SH, "600000", KlineCategory.DAY, 0, 100) + + # 自动从候选列表中选延迟最低的服务器 + with TdxClient.from_best_host() as c: + count = c.get_security_count(Market.SH) """ def __init__( self, - host: str = _DEFAULT_HOST, + host: str = KNOWN_HOSTS[0], port: int = _DEFAULT_PORT, timeout: float = 15.0, + auto_reconnect: bool = True, ) -> None: + self._host = host + self._port = port + self._timeout = timeout + self._auto_reconnect = auto_reconnect self._conn = TdxConnection(host, port, timeout) + # ------------------------------------------------------------------ # + # 工厂方法:自动优选最低延迟服务器 + # ------------------------------------------------------------------ # + + @classmethod + def from_best_host( + cls, + hosts: list[str] = KNOWN_HOSTS, + port: int = _DEFAULT_PORT, + timeout: float = 15.0, + ping_timeout: float = 5.0, + auto_reconnect: bool = True, + ) -> "TdxClient": + """测量 hosts 中所有服务器延迟,选最低延迟的建立连接。 + + 若所有服务器均不可达,回退到 hosts[0]。 + """ + ranked = ping_all(hosts, port, ping_timeout) + best = ranked[0][0] if ranked else hosts[0] + return cls(best, port, timeout, auto_reconnect) + + @staticmethod + def ping_all( + hosts: list[str] = KNOWN_HOSTS, + port: int = _DEFAULT_PORT, + timeout: float = 5.0, + ) -> list[tuple[str, float]]: + """测量多台服务器延迟,返回按延迟排序的 (host, seconds) 列表。""" + return ping_all(hosts, port, timeout) + + # ------------------------------------------------------------------ # + # 连接管理 + # ------------------------------------------------------------------ # + def connect(self) -> None: self._conn.connect() @@ -64,23 +111,40 @@ class TdxClient: ) -> None: self.close() + # ------------------------------------------------------------------ # + # 内部执行:含自动重连 + # ------------------------------------------------------------------ # + + def _execute(self, cmd: "BaseCommand[_T]") -> _T: + """执行命令;断线时尝试重连一次再重试(若 auto_reconnect=True)。""" + try: + return self._conn.execute(cmd) + except TdxConnectionError: + if not self._auto_reconnect: + raise + # 重连后重试一次 + self._conn.close() + self._conn = TdxConnection(self._host, self._port, self._timeout) + self._conn.connect() + return self._conn.execute(cmd) + # ------------------------------------------------------------------ # # 市场信息 # ------------------------------------------------------------------ # def get_security_count(self, market: Market) -> int: """获取市场证券总数。""" - return self._conn.execute(GetSecurityCountCmd(market)) + return self._execute(GetSecurityCountCmd(market)) def get_security_list(self, market: Market, start: int) -> list[SecurityInfo]: """获取证券列表(每页约1000条,按 start 分页)。""" - return self._conn.execute(GetSecurityListCmd(market, start)) + return self._execute(GetSecurityListCmd(market, start)) def get_security_quotes( self, stocks: list[tuple[Market, str]] ) -> list[SecurityQuote]: """批量获取实时五档行情(最多80只/次)。""" - return self._conn.execute(GetSecurityQuotesCmd(stocks)) + return self._execute(GetSecurityQuotesCmd(stocks)) # ------------------------------------------------------------------ # # K 线 @@ -95,7 +159,7 @@ class TdxClient: count: int = 800, ) -> list[SecurityBar]: """获取 K 线数据(最多800条/次,按 start 分页)。""" - return self._conn.execute(GetSecurityBarsCmd(market, code, category, start, count)) + return self._execute(GetSecurityBarsCmd(market, code, category, start, count)) def get_index_bars( self, @@ -106,7 +170,7 @@ class TdxClient: count: int = 800, ) -> list[SecurityBar]: """获取指数 K 线数据。""" - return self._conn.execute(GetIndexBarsCmd(market, code, category, start, count)) + return self._execute(GetIndexBarsCmd(market, code, category, start, count)) # ------------------------------------------------------------------ # # 分时 @@ -114,13 +178,13 @@ class TdxClient: def get_minute_time_data(self, market: Market, code: str) -> list[MinuteBar]: """获取今日分时数据(240条)。""" - return self._conn.execute(GetMinuteTimeDataCmd(market, code)) + return self._execute(GetMinuteTimeDataCmd(market, code)) def get_history_minute_time_data( self, market: Market, code: str, date: int ) -> list[MinuteBar]: """获取历史某日分时数据(date: YYYYMMDD)。""" - return self._conn.execute(GetHistoryMinuteTimeDataCmd(market, code, date)) + return self._execute(GetHistoryMinuteTimeDataCmd(market, code, date)) # ------------------------------------------------------------------ # # 逐笔成交 @@ -130,13 +194,13 @@ class TdxClient: self, market: Market, code: str, start: int, count: int = 800 ) -> list[TransactionRecord]: """获取当日逐笔成交(分页)。""" - return self._conn.execute(GetTransactionDataCmd(market, code, start, count)) + return self._execute(GetTransactionDataCmd(market, code, start, count)) def get_history_transaction_data( self, market: Market, code: str, date: int, start: int, count: int = 800 ) -> list[TransactionRecord]: """获取历史逐笔成交(date: YYYYMMDD,分页)。""" - return self._conn.execute( + return self._execute( GetHistoryTransactionDataCmd(market, code, date, start, count) ) @@ -146,23 +210,23 @@ class TdxClient: def get_xdxr_info(self, market: Market, code: str) -> list[XdxrRecord]: """获取除权除息历史记录。""" - return self._conn.execute(GetXdxrInfoCmd(market, code)) + return self._execute(GetXdxrInfoCmd(market, code)) def get_finance_info(self, market: Market, code: str) -> FinanceInfo: """获取最新财务数据。""" - return self._conn.execute(GetFinanceInfoCmd(market, code)) + return self._execute(GetFinanceInfoCmd(market, code)) def get_company_info_category( self, market: Market, code: str ) -> list[CompanyInfoCategory]: """获取公司信息文件目录。""" - return self._conn.execute(GetCompanyInfoCategoryCmd(market, code)) + return self._execute(GetCompanyInfoCategoryCmd(market, code)) def get_company_info_content( self, market: Market, code: str, filename: str, offset: int, length: int ) -> str: """读取公司信息文本。""" - return self._conn.execute( + return self._execute( GetCompanyInfoContentCmd(market, code, filename, offset, length) ) @@ -183,7 +247,7 @@ class AsyncTdxClient: def __init__( self, - host: str = _DEFAULT_HOST, + host: str = KNOWN_HOSTS[0], port: int = _DEFAULT_PORT, timeout: float = 15.0, ) -> None: diff --git a/src/xmtdx/commands/transaction.py b/src/xmtdx/commands/transaction.py index 7fe960b..b356d52 100644 --- a/src/xmtdx/commands/transaction.py +++ b/src/xmtdx/commands/transaction.py @@ -28,7 +28,7 @@ class GetTransactionDataCmd(BaseCommand[list[TransactionRecord]]): def parse_response(self, body: bytes) -> list[TransactionRecord]: - return _parse_transaction_body(body, skip=2) + return _parse_transaction_body(body) class GetHistoryTransactionDataCmd(BaseCommand[list[TransactionRecord]]): diff --git a/src/xmtdx/transport/sync.py b/src/xmtdx/transport/sync.py index c432dc7..f4ba19e 100644 --- a/src/xmtdx/transport/sync.py +++ b/src/xmtdx/transport/sync.py @@ -1,6 +1,7 @@ """同步 TCP 连接(基于 socket)。""" import socket +import time from types import TracebackType from typing import TYPE_CHECKING, TypeVar @@ -17,6 +18,81 @@ _DEFAULT_HOST = "180.153.18.170" _DEFAULT_PORT = 7709 _DEFAULT_TIMEOUT = 15.0 +# 已知可用的通达信行情服务器(按优先级排序) +KNOWN_HOSTS: list[str] = [ + "180.153.18.170", + "180.153.18.171", + "180.153.18.172", + "115.238.56.198", + "115.238.90.165", + "218.75.126.9", + "47.107.75.159", + "59.175.238.38", +] + + +def ping_host( + host: str, + port: int = _DEFAULT_PORT, + timeout: float = 5.0, +) -> float | None: + """测量连接到指定服务器并完成握手所需的时间(秒)。 + + 返回延迟(秒),连接失败时返回 None。 + """ + t0 = time.monotonic() + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(timeout) + try: + sock.connect((host, port)) + # 发送第一条握手命令并等待响应作为可用性验证 + sock.sendall(SETUP_COMMANDS[0]) + hdr_buf = _recv_exact_sock(sock, HEADER_SIZE) + hdr = parse_header(hdr_buf) + if hdr.zipsize > 0: + _recv_exact_sock(sock, hdr.zipsize) + return time.monotonic() - t0 + except OSError: + return None + finally: + try: + sock.close() + except OSError: + pass + + +def ping_all( + hosts: list[str] = KNOWN_HOSTS, + port: int = _DEFAULT_PORT, + timeout: float = 5.0, +) -> list[tuple[str, float]]: + """并发测量多台服务器延迟,返回按延迟排序的 (host, latency_seconds) 列表。 + + 不可达的服务器不包含在结果中。 + """ + import concurrent.futures + + results: list[tuple[str, float]] = [] + with concurrent.futures.ThreadPoolExecutor(max_workers=len(hosts)) as pool: + futures = {pool.submit(ping_host, h, port, timeout): h for h in hosts} + for fut in concurrent.futures.as_completed(futures): + host = futures[fut] + latency = fut.result() + if latency is not None: + results.append((host, latency)) + results.sort(key=lambda t: t[1]) + return results + + +def _recv_exact_sock(sock: socket.socket, n: int) -> bytes: + buf = bytearray() + while len(buf) < n: + chunk = sock.recv(n - len(buf)) + if not chunk: + raise TdxConnectionError("连接被服务器关闭") + buf.extend(chunk) + return bytes(buf) + class TdxConnection: """同步通达信 TCP 连接。 @@ -112,10 +188,4 @@ class TdxConnection: def _recv_exact(self, n: int) -> bytes: """循环 recv 直到读满 n 字节。""" assert self._sock is not None - buf = bytearray() - while len(buf) < n: - chunk = self._sock.recv(n - len(buf)) - if not chunk: - raise TdxConnectionError("连接被服务器关闭") - buf.extend(chunk) - return bytes(buf) + return _recv_exact_sock(self._sock, n) diff --git a/tests/fixtures/company_info_category.hex b/tests/fixtures/company_info_category.hex new file mode 100644 index 0000000..dafdb8b --- /dev/null +++ b/tests/fixtures/company_info_category.hex @@ -0,0 +1 @@ +1000d7eed0c2cce1cabe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22c0000b9abcbbeb8c5bff600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a22c0000ec510000b2c6cef1b7d6cef600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e7e00003fd70000b9c9b6abd1d0bebf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cd55010061580000b9c9b1bebde1b9b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002eae01002f270000d7cab1bed4cbd7f700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005dd501005d360000d2b5c4dab5e3c6c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003630303030302e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004cba0b020037210100d0d0d2b5b7d6cef6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b3630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a3f12c0300c1240000b9abcbbeb4f3cac200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a13630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000edb251030065430600d1d0bebfb1a8b8e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e43630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ce179509009e1a0100beadd3aab7d6cef600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bb3630303030302e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b5af0a0029790000d6f7c1a6d7b7d7d9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006d3630303030302e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007ede280b0031680000b7d6baecc0a9b9c900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000273630303030302e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0f910b00edea0400b8dfb2e3d6cec0ed00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013630303030302e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081fc7b1000b16d0000c1fabba2b0f1b5a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e3630303030302e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016c41d1100b51e0000b9d8c1aab8f6b9c900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000473630303030302e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000cfade9100017340000 \ No newline at end of file diff --git a/tests/fixtures/company_info_category.json b/tests/fixtures/company_info_category.json new file mode 100644 index 0000000..995910d --- /dev/null +++ b/tests/fixtures/company_info_category.json @@ -0,0 +1,8 @@ +{ + "num_records": 16, + "first": { + "filename": "600000.txt", + "start": 0, + "length": 11426 + } +} \ No newline at end of file diff --git a/tests/fixtures/company_info_content.hex b/tests/fixtures/company_info_content.hex new file mode 100644 index 0000000..524f62d --- /dev/null +++ b/tests/fixtures/company_info_content.hex @@ -0,0 +1 @@ +01003630303030300100a22ca1eed7eed0c2cce1cabea1ee20a1f336303030303020c6d6b7a2d2f8d0d020b8fcd0c2c8d5c6daa3ba323032362d30342d3130a1f320b8dbb0c4d7cad1b620c1e9cda856392e300d0aa1eea1beb8dbb0c4d7cad1b6a1bfcbf9d4d8cec4d5c2a1a2cafdbeddbdf6b9a9b2cebfbca3accab9d3c3c7b0cef1c7ebd7d0cfb8bacbcab5a3acb7e7cfd5d7d4b8baa1a3a1ee0d0aa1efb1bec0b8b0fcc0a8a1be312ed7eed0c2cce1d0d1a1bfa1be322ebbfab9b9b3d6b9c9b1e4bbafa1bfa1be332eb8c5c4eeb0e5bfe9a1bfa1be342eb7e7cfd5cce1cabea1bfa1ef0d0a0d0aa1be312ed7eed0c2cce1d0d1a1bf20a1ef32303236d2bbbcbeb1a8d4a4d4bcc5fbc2b6cab1bce43a20323032362d30342d33300d0aa9b0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9b40d0aa3fca1efd7eed0c2d6f7d2aad6b8b1eaa1ef202020202020a3fc20202020323032352d31322d3331a3fc20202020323032352d30392d3330a3fc20202020323032352d30362d3330a3fc20202020323032352d30332d3331a3fc20202020323032342d31322d3331a3fc20202020323032342d30392d3330a3fc0d0aa3fcc3bfb9c9cad5d2e628d4aa2920202020202020202020a3fc2020202020202020312e35323030a3fc2020202020202020312e32383030a3fc2020202020202020302e39393030a3fc2020202020202020302e35373030a3fc2020202020202020312e33363030a3fc2020202020202020312e31333030a3fc0d0aa3fcc3bfb9c9bebbd7cab2fa28d4aa292020202020202020a3fc2020202020202032322e31333030a3fc2020202020202032322e34303030a3fc2020202020202032322e35373030a3fc2020202020202032322e37333030a3fc2020202020202032322e33363030a3fc2020202020202032312e39303030a3fc0d0aa3fcbebbd7cab2facad5d2e6c2ca28252920202020202020a3fc2020202020202020362e37363030a3fc2020202020202020352e36373030a3fc2020202020202020342e33333030a3fc2020202020202020322e35353030a3fc2020202020202020362e32383030a3fc2020202020202020352e32353030a3fc0d0aa3fcd7dcb9c9b1be28b9c929202020202020202020202020a3fc202020203333332e30353834d2daa3fc202020203331332e35343639d2daa3fc20202020203330322e363435d2daa3fc202020203239332e35323138d2daa3fc202020203239332e35323138d2daa3fc202020203239332e35323138d2daa3fc0d0aa3fcc1f7cda841b9c928b9c9292020202020202020202020a3fc202020203333332e30353834d2daa3fc202020203331332e35343639d2daa3fc20202020203330322e363435d2daa3fc202020203239332e35323138d2daa3fc202020203239332e35323138d2daa3fc202020203239332e35323138d2daa3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fc323032352d31322d33312020c3bfb9c9d7cab1beb9abbbfd28d4aa293a342e303337322020d3aad2b5d7dccad5c8eb28d4aa293a313733392e3634d2da2020cdacb1c8d4f6312e3838252020c3bfb9c9beadd3aacfd6bdf0c1f7c1bf28d4aa293a31312e323830302020202020202020202020202020a3fc0d0aa3fc323032352d31322d33312020c3bfb9c9ceb4b7d6c0fbc8f328d4aa293a372e353335312020bebbc0fbc8f328d4aa293a3530302e3137d2da2020cdacb1c8d4f631302e3532252020beadd3aabbeeb6afcfd6bdf0bebbc1f7c1bfd4f6b3a4c2ca3a3231322e3634252020202020202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fca1efd7eed0c2b9abb8e63a323032362d30342d3038c6d6b7a2d2f8d0d02836303030303029d6d0d0c5d6a4c8afb9c9b7ddd3d0cfdeb9abcbbea1a2b9facca9baa3cda8d6a4c8afb9c9b7ddd3d0cfdeb9abcbbeb9d8d3dac9cfbaa3c6d6b6abb7a2d5b9d2f8d0d0b9c9b7ddd3d0cfdeb9abcbbeb9ab20a3fc0d0aa3fcbfaab7a2d0d0bfc9d7aabbbbb9abcbbed5aec8afb3d6d0f8b6bdb5bcb1a3bcf6d7dcbde1b1a8b8e6cae928cfeabcfbb9abcbbeb4f3cac2292020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa3fca1efd7eed0c2b1a8b5c03a323032362d30342d3130c6d6b7a2d2f8d0d0bbf1c5fab3c9ceaacafdd7d6c8cbc3f1b1d2d2b5cef1d4cbd3aabbfab9b928cfeabcfbd2b5c4dab5e3c6c029202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fca1efd7eed0c2b7d6baecc0a9b9c9bacdceb4c0b4cac2cfee3a202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa3fca1beb7d6baeca1bf3a32303235c4eab6c8203130c5c9342e32d4aa28baaccbb02928d4a4b0b8292020a3a8cfeabcfbb7d6baecc0a9b9c9a3a920202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa3fca1beb7d6baeca1bf3a32303235b0ebc4eab6c820c0fbc8f3b2bbb7d6c5e428bef6b0b82920202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fca1efccd8b1f0cce1d0d13a2020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa3fca1efcdb6d7cabba5b6af3a323032362d30342d3039d3d032ccf5b9d8d3dac6d6b7a2d2f8d0d0b9abcbbecdb6d7cad5dfbba5b6afc4dac8dd28cfeabcfbd2b5c4dab5e3c6c029202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa3fca1efb9c9b6abbba7cafdb1e4bbaf3abdd8d6b9323032362d30322d32382cb9abcbbeb9c9b6abcafd3136303831332cb1c8c9cfc6da28323032352d31322d333129d4f6bcd33338343836bba72cb7f9b6c833312e34362528cfeabcfbd6f7c1a6d7b7d7d9292020202020202020202020202020202020a3fc0d0aa3fca1efd6f7d3aad2b5cef13abeadd6d0b9fac8cbc3f1d2f8d0d0bcb0b9fabcd2bdf0c8dabce0b6bdb9dcc0edd7dcbed6c5fad7bcb5c4c9ccd2b5d2f8d0d0d2b5cef1a3acc8dad7cad7e2c1ded2b5cef1a3acd0c5cdd0d2b5cef1a3acc0edb2c6d2b5cef1d2d4bcb0beadcfe3b8dbd6a4c8afbcb0c6da20a3fc0d0aa3fcbbf5cac2cef1bce0b2ecceafd4b1bbe1b0e4b7a2b5c4cfe0b9d8c5c6d5d5cbf9b9e6b6a8b5c4cdb6d7cad2f8d0d0d2b5cef1bacdd7cab2fab9dcc0edd2b5cef1a1a320202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa9b8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9bc0d0a0d0aa1efbdfccee5c4eac3bfb9c9cad5d2e6b6d4b1c8a3ba0d0aa9b0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9b40d0aa3fcc4eab6c820202020202020202020a3fc2020202020202020202020c4eab6c8202020202020202020a3fc2020202020202020202020c8fdbcbe202020202020202020a3fc2020202020202020202020d6d0c6da202020202020202020a3fc2020202020202020202020d2bbbcbe202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fc3230323520202020202020202020a3fc202020202020202020202020202020202020312e35323030a3fc202020202020202020202020202020202020312e32383030a3fc202020202020202020202020202020202020302e39393030a3fc202020202020202020202020202020202020302e35373030a3fc0d0aa3fc3230323420202020202020202020a3fc202020202020202020202020202020202020312e33363030a3fc202020202020202020202020202020202020312e31333030a3fc202020202020202020202020202020202020302e38393030a3fc202020202020202020202020202020202020302e35373030a3fc0d0aa3fc3230323320202020202020202020a3fc202020202020202020202020202020202020312e30373030a3fc202020202020202020202020202020202020302e38383030a3fc202020202020202020202020202020202020302e37363030a3fc202020202020202020202020202020202020302e35313030a3fc0d0aa3fc3230323220202020202020202020a3fc202020202020202020202020202020202020312e35363030a3fc202020202020202020202020202020202020312e33313030a3fc202020202020202020202020202020202020312e30303030a3fc202020202020202020202020202020202020302e36343030a3fc0d0aa3fc3230323120202020202020202020a3fc202020202020202020202020202020202020312e36323030a3fc202020202020202020202020202020202020312e33343030a3fc202020202020202020202020202020202020302e39393030a3fc202020202020202020202020202020202020302e36313030a3fc0d0aa9b8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9bc0d0a0d0aa1efd7eed0c2c6c0bcb628cfeabcfbd1d0bebfb1a8b8e6290d0aa9b0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9b40d0aa3fc202020b7a2c9fac8d5c6da202020a3fc20202020202020202020202020c6c0bcb6bbfab9b920202020202020202020202020a3fc202020202020202020202020202020d1d0bebfd4b120202020202020202020202020a3fc202020cdb6d7cac6c0bcb6202020a3fc20c4bfb1eabcdbb8f128d4aa2920a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fc2020323032362d30342d30312020a3fc20202020202020202020202020b9e3b7a2d6a4c8af20202020202020202020202020a3fcc4dfbefc5cc1d6bba220202020202020202020202020202020202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc20202020202020202031332e3238a3fc0d0aa3fc2020323032362d30332d33312020a3fc20202020202020202020202020bbaacca9d6a4c8af20202020202020202020202020a3fcc9f2beea5cbad8d1c5cda45cc6d1dde7d2c020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc20202020202020202031322e3831a3fc0d0aa3fc2020323032362d30342d30312020a3fc20202020202020202020202020d6d0cca9d6a4c8af20202020202020202020202020a3fcb4f7d6beb7e65cb5cbc3c0befd202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30332d33312020a3fc20202020202020202020202020c6bdb0b2d6a4c8af20202020202020202020202020a3fcd4ac86b4c6e65cc0eec1e9ac4c202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30332d33302020a3fc20202020202020202020202020d5e3c9ccd6a4c8af20202020202020202020202020a3fcc7f1b9dabbaa5cb6c5c7d8b4a85cb5cbbad8b7bd5cd6dcd4b4202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30332d33312020a3fc20202020202020202020202020b9fad0c5d6a4c8af20202020202020202020202020a3fccdf5bda35cb3c2bfa1c1bc2020202020202020202020202020202020202020202020a3fc2020202020d6d0d0d42020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30332d33312020a3fc20202020202020202020202020b9facca9baa3cda820202020202020202020202020a3fcc2ede6c3e6c35cc0eec8f3c1e8202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc20202020202020202031342e3431a3fc0d0aa3fc2020323032362d30332d33312020a3fc20202020202020202020202020d6d0d0c5bda8cdb620202020202020202020202020a3fcc2edf6efc5f45cc0eeb3bf5ccdf5d0c0d3ee20202020202020202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30332d31372020a3fc20202020202020202020202020c6bdb0b2d6a4c8af20202020202020202020202020a3fcd4ac86b4c6e65cc0eec1e9ac4c202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30312d31332020a3fc20202020202020202020202020d5e3c9ccd6a4c8af20202020202020202020202020a3fcc7f1b9dabbaa5cb6c5c7d8b4a85cc1bab7efbde05cd6dcd4b4202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30312d31342020a3fc20202020202020202020202020d6d0cca9d6a4c8af20202020202020202020202020a3fcb4f7d6beb7e65cb5cbc3c0befd5cd1eeb3acc2d72020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30312d31342020a3fc20202020202020202020202020b9fabaa3d6a4c8af20202020202020202020202020a3fcc1d6bcd3c1a65cd0ecc4fdb1cc202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc202020202020202020202020202da3fc0d0aa3fc2020323032362d30312d31332020a3fc20202020202020202020202020b9facca9baa3cda820202020202020202020202020a3fcc2ede6c3e6c35cc0eec8f3c1e8202020202020202020202020202020202020202020a3fc2020202020d4f6b3d62020202020a3fc20202020202020202031352e3231a3fc0d0aa3fc2020323032362d30312d31332020a3fc20202020202020202020202020d6d0d0c5bda8cdb620202020202020202020202020a3fcc2edf6efc5f45cc0eeb3bf5ccdf5d0c0d3ee20202020202020202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc20202020202020202031352e3030a3fc0d0aa3fc2020323032362d30312d31342020a3fc20202020202020202020202020b9e3b7a2d6a4c8af20202020202020202020202020a3fcc4dfbefc5cc1d6bba220202020202020202020202020202020202020202020202020a3fc2020202020c2f2c8eb2020202020a3fc20202020202020202031352e3635a3fc0d0aa9b8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9bc0d0a0d0aa1be322ebbfab9b9b3d6b9c9b1e4bbafa1bf0d0aa9b0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9b40d0aa3fcb1a8b8e6c8d5c6da2020202020202020202020202020a3fc20202020323032352d31322d3331a3fc20202020323032352d30392d3330a3fc20202020323032352d30362d3330a3fc20202020323032352d30332d3331a3fc20202020323032342d31322d3331a3fc20202020323032342d30392d3330a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcbbfab9b9cafdc1bf28bcd22920202020202020202020a3fc2020202020202020202020353637a3fc2020202020202020202020203635a3fc2020202020202020202020383239a3fc2020202020202020202020313036a3fc2020202020202020202020353337a3fc2020202020202020202020203835a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcc0dbbcc6b3d6d3d028b9c92920202020202020202020a3fc202020203236312e31353638d2daa3fc202020203233352e36393639d2daa3fc202020203234302e34303936d2daa3fc202020203232352e36343734d2daa3fc202020203233342e30353039d2daa3fc202020203232362e33393732d2daa3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcbdcfc9cfc6dab1e4bbaf28b9c9292020202020202020a3fc202020202032352e34353939d2daa3fc20202020202d342e37313237d2daa3fc202020202031342e37363232d2daa3fc20202020202d382e34303335d2daa3fc202020202020372e36353337d2daa3fc20202020202d342e34363736d2daa3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcc0dbbcc6b3d6b2d6b1c8c0fd20202020202020202020a3fc202020202020202037382e343125a3fc202020202020202037352e313725a3fc202020202020202037392e343425a3fc202020202020202037362e383825a3fc202020202020202037392e373425a3fc202020202020202037372e313325a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcbbf9bdf0b3d6b9c928b9c92920202020202020202020a3fc202020202031302e35303831d2daa3fc202020202020312e37353132d2daa3fc202020202031322e33343136d2daa3fc202020202020312e39303636d2daa3fc202020202031302e31393032d2daa3fc202020202020312e34383239d2daa3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcbbf9bdf0b3d6b2d6b1c8c0fd20202020202020202020a3fc202020202020202020332e313625a3fc202020202020202020302e353625a3fc202020202020202020342e303825a3fc202020202020202020302e363525a3fc202020202020202020332e343725a3fc202020202020202020302e353125a3fc0d0aa9b8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9bc0d0ad7a2a3bad2d4c9cfcafdbeddc8a1d7d4bbf9bdf0b3d6b9c9bacdb9abcbbecaaeb4f3c1f7cda8b9c9b6aba3acbcbeb6c8cafdbeddceb4b0fcbaacbbf9bdf0b3d6b9c9c3f7cfb8d7eebdfcd2bbc6dacafdbeddbfc9c4dcd2f2ceaabbf9bdf0cdb6d7cad7e9bacfbbf2b9abcbbeb6a8c6dab1a8b8e6ceb4c5fb20200d0ac2b6cdeab1cfa3acb5bcd6c2bbe3d7dccafdbeddb2bbb9bbcdead5fba1a320202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200d0a0d0aa1be332eb8c5c4eeb0e5bfe9a1bf0d0aa9b0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9b40d0aa3fcb8c5c4eec3fbb3c62020202020202020a3fcb8c5c4eebde2cef62020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcbfe7beb3d6a7b8b62843495053292020a3fc43495053cac7ced2b9fad6d8d2aab5c4bdf0c8dacad0b3a1bbf9b4a1c9e8caa9a3acd4dad6fac1a6c8cbc3f1b1d2b9fabccabbafb5c8b7bdc3e6b7a2bbd3d7c5d6d8d2aad7f7d3c3a1a3b9abcbbecac7cad7c5fad6b1bdd3b2ced3ebd5dfd6aed2bba1a3a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcd6a4bdf0b3d6b9c92020202020202020a3fcbdd8d6b932303232c4ea3033d4c23331c8d52cd6d0d1ebbbe3bdf0d7cab2fab9dcc0edd3d0cfded4f0c8ceb9abcbbeb3d6d3d0c6d6b7a2d2f8d0d033383731372e3437cdf2b9c9a1a3202020202020202020202020202020202020202020202020202020a3fc0d0aa9c0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9e0a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9c80d0aa3fcd0c5cdd0b8c5c4ee2020202020202020a3fc32303136c4ea33d4c22c3136332e35d2dacad5b9bab2a2b1edc9cfbaa3d0c5cdd03b3137c4eac9cfbaa3d0c5cdd0beadd3aacafdbeddc8e7cfc22cd7cab2fab9e6c4a3312e3233cdf2d2dad4aa2cd3aad2b5cad5c8eb34332e3435d2dad4aa2cbebbc0fba3fc0d0aa3fc20202020202020202020202020202020a3fcc8f332302e3431d2dad4aaa1a3202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020a3fc0d0aa9b8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9d8a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9bc0d0a28c3e2d4f0c9f9c3f7a3bac4dac8ddc0b4d4b4d3dabba5c1aacdf8a3acb2bbb9b9b3c9cdb6d7cabda8d2e9a3acc7ebcdb6d7cad5dfb8f9beddb2bbcdacd0d0c7e9b6c0c1a2c5d0b6cf290d0a0d0aa1be342eb7e7cfd5cce1cabea1bf0d0aa1bebce0b9dccecad1afa1bf0d0ad4ddcedecafdbedd0d0a0d0aa1becea5b9e6bbfcb2e9a1bf0d0ad4ddcedecafdbedd0d0a0d0aa1beccd8b1f0b4a6c0eda1bf0d0ad4ddcedecafdbedd0d0a0d0aa9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a40d0ac3e2d4f0ccf5bfee0d0a31a1a2b1beb9abcbbec1a6c7f3b5abb2bbb1a3d6a4cafdbeddb5c4cdeac8abd7bcc8b7a3accbf9cce1b9a9b5c4d0c5cfa2c7ebd2d4d6d0b9fad6a4bce0bbe1d6b8b6a8c9cfcad0b9abcbbed0c5cfa2c5fbc2b6c3bdcce5ceaad7bca3acb8dbb0c4d7cad1b6b2bbb6d4d2f2b8c3d7cac1cfc8abb2bfbbf2b2bf0d0ab7d6c4dac8ddb6f8d2fdd6c2b5c4d3afbff7b3d0b5a3c8cebaced4f0c8cea1a30d0a32a1a2d4dad7f7d5dfcbf9d6aac7e9b5c4b7b6cea7c4daa3acb1bebbfab9b9a1a2b1bec8cbd2d4bcb0b2c6b2fac9cfb5c4c0fbbaa6b9d8cfb5c8cbd3ebcbf9c6c0bcdbbbf2cdc6bcf6b5c4b9c9c6b1c3bbd3d0c0fbbaa6b9d8cfb5a3acb1bebbfab9b9a1a2b1bec8cbb7d6cef6bdf6b9a9b2cebfbca3acb2bb0d0ad7f7ceaacdb6d7cabef6b2dfb5c4d2c0bedda3acb8dbb0c4d7cad1b6b2bbb6d4d2f2beddb4cbb2d9d7f7b2fac9fab5c4d3afbff7b3d0b5a3c8cebaced4f0c8cea1a30d0aa9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a40d0ac8e7b9fbc4fab6d4cafdbeddd3d0d2c9cecac7ebc1aacfb5c9cfcad0b9abcbbea3acc1aacfb5b5e7bbb0ceaaa3ba3032312d36333631313232360d0ac8e7b9fbc4fab6d4b8dbb0c4d7cad1b6cce1b9a9b5c4463130d7cad1b6c4dac8ddd3d0c8cebaceb5c4d2e2bcfbbbf2d5dfbda8d2e9a3acc7ebc1aacfb5ced2c3c7bfcdb7fec8c8cfdfa3ba303839383638353030383836a3a8c9cfcee7393a33302d31313a3330a3accfc2cee731333a30302d31353a3030a3a90d0aced2c3c7bdabbddfc1a6ceaac4facce1b9a9d7a8d2b5a1a2beabd7bca1a2bfecbdddb5c4bdf0c8dad7cad1b6b7fecef1a1a30d0aa9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a4a9a40d0a00 \ No newline at end of file diff --git a/tests/fixtures/company_info_content.json b/tests/fixtures/company_info_content.json new file mode 100644 index 0000000..0fdcf62 --- /dev/null +++ b/tests/fixtures/company_info_content.json @@ -0,0 +1,4 @@ +{ + "length": 8070, + "prefix": "☆最新提示☆ ◇600000 浦发银行 更新日期:2026-04-10◇ 港澳资讯 灵通V9.0\r\n" +} \ No newline at end of file diff --git a/tests/fixtures/finance_info.hex b/tests/fixtures/finance_info.hex new file mode 100644 index 0000000..1da9b08 --- /dev/null +++ b/tests/fixtures/finance_info.hex @@ -0,0 +1 @@ +0100013630303030305f484b4a10000100eb253501460a31015f484b4a00c0f5444aa42c4c86d6224d00000000000000005c8fc23fcf3a1650000000009138814ce8a30c4b400b1d4800000000c05ee54a643b004d79c4424eaee7254d948fe54c00000000907f4c4cf4f4934b6b36b34d48e26e4c000000000c9b4b4ca247404cbacc3e4c44566f4d3d0ab14100004041 \ No newline at end of file diff --git a/tests/fixtures/finance_info.json b/tests/fixtures/finance_info.json new file mode 100644 index 0000000..969ccc0 --- /dev/null +++ b/tests/fixtures/finance_info.json @@ -0,0 +1,5 @@ +{ + "liutong_guben": 33305837500.0, + "zong_guben": 33305837500.0, + "meigujing_zichan": 22.1299991607666 +} \ No newline at end of file diff --git a/tests/fixtures/history_minute_time.hex b/tests/fixtures/history_minute_time.hex new file mode 100644 index 0000000..44bdbca --- /dev/null +++ b/tests/fixtures/history_minute_time.hex @@ -0,0 +1 @@ +f000ec5124418510ee03bc9c014123a9344101805000008744010d8032000bae3802189b2c42039a21010fad3a038101bc68012f844f4117ad3c000d9826011a8f3f010fa8204106a312000a9d1f022ab5580012b4294404ac4e42489f490041b90e0043b11c004286180201ac120001b013424384240141b3370101a80f414096110202a4144101a60d0204ab164103901d01028b0d000b90440002b10b03108d3400059c114209a62f4204a53b0001a50c0001be1100019a0f0104b9210105891f0008a632000386124103981f0005ba3700029d1b0001b9080206a120410381150004941d4202923500019e254241a71a00418f0f4143b81c0301ad1f4242a92001408d124141841b0140a5140040982b4141ba0b0041851b4141ba0e0042b21d0042bb134143841e0042af130042950f0041850b004194090141b108414281104149a13d0043a5170043b0140048b5400041b50701419206414185070141bc090041ab074453b357014485170141ac094244ad13414e933d414c832e00478b1b0156b36901438a10424ab32d0247ad2d41499b3241419c060142b20a414587170143961341468a1b024f93694148a03241479b24034296120242962000419c150043a13941409e054243bf184148933700438b120241be0c4244a91d0042831100419c0a41449b190444bc4242449c210042b8150341a7244243b2214243961b0142ab160042b5150141b3070041bb100141b2100040bd040042b51e4142ab16024186114141910b0041b30e414194090041930c0041ac080141b9164142971a0042b61b0240b80c00409d0e0040ba0a004198270140b00400408f104141be15014099090101866341409a104143b4810141429f3201408c104141a7140140be110041951601409a0c4241be1501409d1401408a170040a9064140800e0041b5200404b4544200a41801018f3000019d110000a40a0000a10e0001b710410082170101b32d0000b2094240811b01018d400000b7190100a110010283214100b50e0100a20a00019a0f4100840c0202a61c000287204200a50f01019c130202bd1a0104902e41049a310002a01f4101bd170202871c41049f340002af200002ae1f00019e0e0001b8144101b81401018e104101bf130001ab130001a50a0001b1150003b633000191150001b1194101be274101971f4240a41f004098260040a61641419d2441459d7b014181140140aa130100971200009b0c0000ac160203866c4100a0110101ab1a41019a244100a51c0200810e4100b20e00008c0e4100ac1b4140be1b010094230000980e0000851d0000ac1f000084164140961e0000170000000202a07b \ No newline at end of file diff --git a/tests/fixtures/history_minute_time.json b/tests/fixtures/history_minute_time.json new file mode 100644 index 0000000..5135622 --- /dev/null +++ b/tests/fixtures/history_minute_time.json @@ -0,0 +1,7 @@ +{ + "num_records": 240, + "first": { + "price": 10.29, + "vol": 10044 + } +} \ No newline at end of file diff --git a/tests/fixtures/history_transaction.hex b/tests/fixtures/history_transaction.hex new file mode 100644 index 0000000..98bec15 --- /dev/null +++ b/tests/fixtures/history_transaction.hex @@ -0,0 +1 @@ +0a00ec512441800386103200008003411301008003009d0401008003003001008003009d02010080034183020100800301b50202008003411e0100810300170100840302a07b0200 \ No newline at end of file diff --git a/tests/fixtures/history_transaction.json b/tests/fixtures/history_transaction.json new file mode 100644 index 0000000..3eae59f --- /dev/null +++ b/tests/fixtures/history_transaction.json @@ -0,0 +1,9 @@ +{ + "num_records": 10, + "first": { + "hour": 14, + "minute": 56, + "price": 10.3, + "vol": 50 + } +} \ No newline at end of file diff --git a/tests/fixtures/minute_time.hex b/tests/fixtures/minute_time.hex new file mode 100644 index 0000000..a8f5302 --- /dev/null +++ b/tests/fixtures/minute_time.hex @@ -0,0 +1 @@ +f0000000013630303030303e109d0f04040643acfaa60edd0f9889349483013a6ec94da7831cb2851841a6e2020001bd0788124102a8cd0187314203906aab11560fa00f9f01ae920144d203a9a30201f8019bf6010201be2d0009a346410cbd7e020ba33a4104bf37000593210204b51e000f8d400005aa150008b02d4107843a4101821101049a240005ba32410186150103bb1e0101b50b420598580001833e0203b53e0003881a0001af060002ac0e000c8c5700059c3d4101b20c0101b10a41029c280102a31f0002861c00008d054102962000018215010187190001b0260001af11000193164101a7264100a5200000b9320040a12c4140a60c0040bf0801409014424a95e0010141bd1b0042ba330141b41c4140ae030141a7150040a10e41428d320041b71a4141ae0b0141aa09004198140043bc434141bc1b0141841900418c0e0041ba164141a9130141bd160041ad1c00438c360041a40c414189124147a37d0142a01d00419a1c014094070040a8044140a70a00408c0700409f060140ab0841408d0b0040b4120140850b0040ac130040a7050040a60b4140950a0140990441408b0a0140b3094140800d01409a064140bc090141be430040b1110041be1f00408c07004081160040810d01008d05414082200042b13200408e0500409f080040960b4140bf070042843b00409c040140ba090040bd050040af110040ae0400408907004098050040b80d0041bb1e414088050140930a0040a0064142802e0040910b014182364144b36b0041a30c4141870c0140a9080040860b41418e160140bd0a0040a40d4142803201408c0a41408d0b0140880600418a1f0140960d0040ac0801409b184140b812004099090040b204004087084140a7060140b8020040b4064141a62d0140b3024140970301408c044140aa0f0040af0a0240a8370000af1b4100bd080100a1024100a5040040a22e0040810441408d0a00408e0a0140ad0d004094120040ae06414094100140890541409c0a0140bb0b4140a0060040bd0b0040aa140140b3100100a32101008f2542008b170000aa06010099030100b911000094100000900600018d114101be180101a20f0100940a0000be050000a5040001ac164101a01400028b32000086070000ae030000b31b0000940641009a1a01009b080000890a0000b10a0000b6094100a00700009f214140ae040000b90b0040ac4a41418618024082184140962201009b044140920c01009a0d4140a6250040ae100100af1000008d050000890500009f0e0040b81400008a090000a1150000b40a0000bb080000a5060001983800409a0e0000ad0f4141bd5e0040801c0040961600409b120040b025004092130040bc150040851e414092160040ad1e01408f15004090254140941d0141802d41458fde0101001d0000004143948301 \ No newline at end of file diff --git a/tests/fixtures/minute_time.json b/tests/fixtures/minute_time.json new file mode 100644 index 0000000..837d7d6 --- /dev/null +++ b/tests/fixtures/minute_time.json @@ -0,0 +1,8 @@ +{ + "num_records": 240, + "first": { + "price": 0.01, + "vol": 48, + "unknown_1": 54 + } +} \ No newline at end of file diff --git a/tests/fixtures/security_bars.hex b/tests/fixtures/security_bars.hex new file mode 100644 index 0000000..2233889 --- /dev/null +++ b/tests/fixtures/security_bars.hex @@ -0,0 +1 @@ +0500332635018aa001c20200ea0253fb1c4c32f1c64d3726350100cc0232ea02bc82104c573fb54d38263501149a01ae01721025384c2b39e74d3926350154cc0232cc02d2d52f4c4a73db4d3a263501006814c601a7ba224c3a6ec94d \ No newline at end of file diff --git a/tests/fixtures/security_bars.json b/tests/fixtures/security_bars.json new file mode 100644 index 0000000..4a5eb15 --- /dev/null +++ b/tests/fixtures/security_bars.json @@ -0,0 +1,10 @@ +{ + "num_records": 5, + "first": { + "open": 10.25, + "high": 10.25, + "low": 10.08, + "close": 10.12, + "vol": 41151820.0 + } +} \ No newline at end of file diff --git a/tests/fixtures/security_count.hex b/tests/fixtures/security_count.hex new file mode 100644 index 0000000..47ab6f6 --- /dev/null +++ b/tests/fixtures/security_count.hex @@ -0,0 +1 @@ +0569 \ No newline at end of file diff --git a/tests/fixtures/security_count.json b/tests/fixtures/security_count.json new file mode 100644 index 0000000..23d5b03 --- /dev/null +++ b/tests/fixtures/security_count.json @@ -0,0 +1,3 @@ +{ + "count": 26885 +} \ No newline at end of file diff --git a/tests/fixtures/security_list.hex b/tests/fixtures/security_list.hex new file mode 100644 index 0000000..389b996 --- /dev/null +++ b/tests/fixtures/security_list.hex @@ -0,0 +1 @@ +e8033939393939396400c9cfd6a4d6b8cafdcc48220002bde27745000000003939393939386400a3c1b9c9d6b8cafd1c43220002e3f68145000000003939393939376400a3c2b9c9d6b8cafd1304000002f3b58443000000003030303030316400c9cfd6a4d6b8cafdcc48220002bde27745000000003030303030326400a3c1b9c9d6b8cafd1c43220002e3f68145000000003030303030336400a3c2b9c9d6b8cafd1304000002f3b58443852c5d0d3030303030346400b9a4d2b5d6b8cafdb614160002e1656a45000000003030303030356400c9ccd2b5d6b8cafd3dcf0100020b6b2645372bc2213030303030366400b5d8b2fad6b8cafd7f7100000271797c45000000003030303030376400b9abd3c3d6b8cafd0fc10300025b169345000000003030303030386400d7dbbacfd6b8cafd483206000266e55245000000003030303030396400c9cfd6a433383000c08c06000205fdd745000000003030303031306400c9cfd6a431383000a00f080002d6fe1846000000003030303031316400bbf9bdf0d6b8cafd646640000271c5d645000000003030303031326400b9fad5aed6b8cafd61580300026e546243000000003030303031356400baecc0fbd6b8cafdf4390200029e484845852c5d0d3030303031366400c9cfd6a435300000e9c3020002294c3445000000003030303031376400d0c2d7dbd6b8000024d12100026d865145000000003030303031386400313830bdf0c8da0091f60100025923a745852cf41c3030303031396400d6cec0edd6b8cafd8545050002ac4a9844000000003030303032306400d6d0d0cdd7dbd6b87c2a050002440dda44000000003030303032316400313830d6cec0ed0097d60300029a598444000000003030303032326400bba6b9abcbbed5aee0190000020cb27f433a3100003030303032356400313830bbf9bda80066d50100020eb8d644000000003030303032366400313830d7cad4b400d128010002643dbb45000000003030303032376400313830d4cbcae400f576000002b7324944000000003030303032386400313830b3c9b3a400f2ea01000295996f45000000003030303032396400313830bcdbd6b500c2b5030002f6c8834500000000303030303330640031383052b3c9b3a40e2c05000260941d4500000000303030303331640031383052bcdbd6b5def606000289fa4245000000003030303033326400c9cfd6a4c4dcd4b425d80100025fea1045000000003030303033336400c9cfd6a4b2c4c1cff2c602000200997645852cf81e3030303033346400c9cfd6a4b9a4d2b5a09902000244f00e45000000003030303033356400c9cfd6a4bfc9d1a1cb9200000249f72045000000003030303033366400c9cfd6a4cffbb7d13d3a00000216fa2046000000003030303033376400c9cfd6a4d2bdd2a94c7b0000029d98c645000000003030303033386400c9cfd6a4bdf0c8daeeb80100024ad6a5459f291e203030303033396400c9cfd6a4d0c5cfa23cd8000002c752a845000000003030303034306400c9cfd6a4b5e7d0c52ee00000024b829345a52daa233030303034316400c9cfd6a4b9abd3c31aca0100025a4a2145000000003030303034326400c9cfd6a4d1ebc6f39b9a03000282cdd744000000003030303034336400b3acb4f3c5cc000078370100027c1f1d45273100003030303034346400c9cfd6a4d6d0c5ccb74b0500022f258e45000000003030303034356400c9cfd6a4d0a1c5cc1d24070002dbe6bb45000000003030303034366400c9cfd6a4d6d0d0a1d46f0c0002f86ba345b32ac3213030303034376400c9cfd6a4c8abd6b8bd330f0002f3d07345852c5d0d3030303034386400d4f0c8ced6b8cafdc0fc010002cb43af44000000003030303034396400c9cfd6a4c3f1c6f378110200023e28fc440000000030303030353064003530b5c8c8a80000e9c3020002cbf00e45000000003030303035316400313830b5c8c8a800a00f080002f8e110460000000030303030353264003530bbf9b1be0000e9c3020002c07c3245000000003030303035336400313830bbf9b1be00a00f080002593e3e46000000003030303035346400c9cfd6a4baa3cde2a3d50300021126bd44000000003030303035356400c9cfd6a4b5d8c6f35c32020002e542c044000000003030303035366400c9cfd6a4b9fac6f3c9ee0300025dc29a44000000003030303035376400c8abd6b8b3c9b3a406dd02000212f66e45000000003030303035386400c8abd6b8bcdbd6b566f3060002bf758e45000000003030303035396400c8ab52b3c9b3a400ac60090002dc975045000000003030303036306400c8ab52bcdbd6b5000c770d00023ad78845000000003030303036316400bba6c6f3d5ae333065180000027b033343000000003030303036326400c9cfd6a4bba6c6f34220010002b928ff44000000003030303036336400c9cfd6a4d6dcc6da0dc2030002d2996d45000000003030303036346400b7c7d6dcc6da00003321040002dad05d45000000003030303036356400c9cfd6a4c1facdb7be110500028c0d6445000000003030303036366400c9cfd6a4c9ccc6b701fe020002f9397e45000000003030303036376400c9cfd6a4d0c2d0cbafbe010002bf8c0946000000003030303036386400c9cfd6a4d7cad4b46f6302000291028e45000000003030303036396400cffbb7d138300000bcd40000022fa68f45000000003030303037306400c4dcd4b4b5c8c8a825d8010002027d4a45000000003030303037316400b2c4c1cfb5c8c8a8f2c6020002fd14ab45000000003030303037326400b9a4d2b5b5c8c8a8a09902000224394945000000003030303037336400bfc9d1a1b5c8c8a8cb92000002aaed4245000000003030303037346400cffbb7d1b5c8c8a83d3a000002088bd145000000003030303037356400d2bdd2a9b5c8c8a84c7b0000024befd745000000003030303037366400bdf0c8dab5c8c8a81bac0100023837a445000000003030303037376400d0c5cfa2b5c8c8a83cd8000002fe7fbf45000000003030303037386400b5e7d0c5b5c8c8a82ee0000002623e7f45000000003030303037396400b9abd3c3b5c8c8a81aca010002e5812645000000003030303039306400c9cfd6a4c1f7cda824d12100027fddb544000000003030303039316400bba6b2c6d6d0d0a1501c020002d1d17246000000003030303039326400d7cad4b435300000554602000202b5aa45000000003030303039336400313830b7d6b2e300a00f080002ba1d3c46000000003030303039346400c9cfd6a4c9cfd3ce6c5c0200024c8b9b45000000003030303039356400c9cfd6a4d6d0d3ce3a36060002764e7d45000000003030303039366400c9cfd6a4cfc2d3ce8ae20100022b707a45000000003030303039376400b8dfb6cbd7b0b1b8b7be0100028ff84046000000003030303039386400c9cfd6a446323030f1060a000246aea845000000003030303039396400c9cfd6a446333030ee37060002ee3d1146000000003030303130306400c9cfd6a446353030df3e100002eebcbf4500000000303030313031640035c4ead0c5d3c300c40500000212b57d43000000003030303130326400bba6cdb6d7cac6b7b120020002cf7dff45000000003030303130336400bba6cffbb7d1c6b782520000023ffaec45000000003030303130346400333830c4dcd4b400cbac000002e01abc44000000003030303130356400333830b2c4c1cf00e9290100026f6fbd45000000003030303130366400333830b9a4d2b5003f86010002b912c645000000003030303130376400333830bfc9d1a100d540000002c11f9d45000000003030303130386400333830cffbb7d100552a00000257204146000000003030303130396400333830d2bdd2a9000e3c00000228891446000000003030303131306400333830bdf0c8da001a6b000002a1547645000000003030303131316400333830d0c5cfa200be6500000265122546000000003030303131326400333830b5e7d0c500a35400000278220346000000003030303131336400333830b9abd3c3004929010002855b4745000000003030303131346400b3d6d0f8b2fad2b50e4b010002193ca044000000003030303131356400333830b5c8c8a800c08c060002373a0d46000000003030303131366400d0c5d3c331303000fe190000028c0a4943000000003030303131376400333830b3c9b3a4008e32010002ee718845000000003030303131386400333830bcdbd6b500e04503000242f7244600000000303030313139640033383052b3c9b3a4c5cd0300029b108e4500000000303030313230640033383052bcdbd6b517e1050002a4e92046000000003030303132316400d2bdd2a9d6f7cce2727200000208f7f345000000003030303132326400c5a9d2b5d6f7cce245810000021ebbda44000000003030303132336400313830b6afccac005b0e040002a54ad245000000003030303132356400313830cec8b6a80004eb0300028e7a3746000000003030303132366400cffbb7d135300000ce8c000002be87e645000000003030303132386400333830bbf9b1be00ba8b0600024a811246000000003030303132396400313830b2a8b6af008191040002d74b6946000000003030303133306400333830b2a8b6af004cfd01000236735646000000003030303133316400c9cfd6a4b8dfd0c2b5450000025c176d45000000003030303133326400c9cfd6a43130300062bf0000026881bb45000000003030303133336400c9cfd6a4313530009e2601000233e9e345000000003030303133346400c9cfd6a4d2f8d0d0bd8b0100020f247544000000003030303133356400313830b8dfb1b400eb6f0100029220bc45000000003030303133366400313830b5cdb1b400f7c702000200fb4646000000003030303133376400333830b8dfb1b40036f4000002cf4cc445000000003030303133386400333830b5cdb1b400b682010002b0150646000000003030303133396400c9cfd6a4d7aad5aede8401000297d0da43000000003030303134316400333830b6afccac0068d402000259107e45000000003030303134326400333830cec8b6a800059c0300027c6a2046000000003030303134356400d3c5cac6d7cad4b4ddb7010002f97d1046000000003030303134366400d3c5cac6d6c6d4ecf2510100022cc2fe45000000003030303134376400d3c5cac6cffbb7d17f56000002d489c845000000003030303134386400cffbb7d1c1eccfc83183020002ee0f0d46000000003030303134396400313830baecc0fb00d8e1010002196c8145000000003030303135306400333830baecc0fb00117e0000024afa3c46372bf41c3030303135316400c9cfb9fabaecc0fbe615010002fba3c644000000003030303135326400c9cfd1ebbaecc0fbfad801000257733745000000003030303135336400c9cfc3f1baecc0fbf67400000267164f45000000003030303135356400cad0d6b5b0d9c7bfd19a05000236a94445000000003030303135386400c9cfd6a4bbb7b1a3bd5e010002ab86aa44000000003030303135396400bba6b9c9cda8000064191d00027df96545000000003030303136306400bba6d0c2cbbfc2b7935c050002b4b11545000000003030303136316400bba6d6d0b9fad4ec5794020002550ee044000000003030303136326400bba6bba5c1aa2b00260a0100022eb84f4500000000303030313730640035304148d3c5d1a1ac6f0100023eb2bb45000000003030303330306400bba6c9ee33303000c1350c0002cab18e45000000003030303531306400d6d0d6a441353030f2181200029b17b245000000003030303638306400bfc6b4b4d7dbd6b8726f02000273a2d744000000003030303638316400bfc6b4b4bcdbb8f1726f020002de21d044000000003030303638326400bfc6b4b4d0c5cfa2f35d0000024e150045000000003030303638336400bfc6b4b4c9faceef0737000002c9be8544000000003030303638356400bfc6b4b4d0bec6ac675600000298183045000000003030303638376400bfc6b4b4b8dfd7b0db3d0000028b02a9449f29d91f3030303638386400bfc6b4b435300000d68100000247fea744000000003030303638396400bfc6b4b4b2c4c1cf8640000002d56fa244852c5d0d3030303639306400bfc6b4b4b3c9b3a48f3a0000021054fd44000000003030303639316400bfc6b4b4455347004d5300000245d5ae44000000003030303639326400bfc6b4b4d0c2c4dc445e000002e3b99644000000003030303639336400bfc6b4b4bbfad0b5ca32000002b89fc344a32c9e1a3030303639356400bfc6b3a4c8fdbdc7425f000002d3798344000000003030303639376400bfc6b4f3cde5c7f8fd37000002e3c7b244000000003030303639386400bfc6b4b43130300010980000021116c444000000003030303639396400bfc6b4b43230300021c0000002d547bc44512f5d0d3030303830326400353030bba6cad000e803060002dfe3f645000000003030303831346400cfb8b7d6d2bdd2a974750000022aea0446000000003030303831396400d3d0c9abbdf0caf44b0002000284b61f46000000003030303832336400383030d3d0c9ab0058df0100020d8d3946000000003030303832376400d6d0d6a4bbb7b1a38225030002bd90ee44512f5d0d3030303834376400ccdad1b6bcc3b0b26d0002000218f16045000000003030303834396400333030b7c7d2f8004d1c01000278991346000000003030303835316400b0d9b7a23130300016ce010002c8b2aa4606309d243030303835326400d6d0d6a4313030308fc40f0002928bf74500000000303030383533640043535357cbbfc2b7cd9801000206f4ce44000000003030303835346400353030d4adc1cf002ace0100021af7d045000000003030303835356400d1ebcad335303000b7aa0f0002a54fca44000000003030303835366400353030b9a4d2b500378d020002d22ef745000000003030303835376400353030d2bdd2a900f36c0000025a462546000000003030303835386400353030d0c5cfa2008f2a01000256bc2946000000003030303836306400bde1b9b9b5f7d5fb49de030002001d9c440000000030303038363364004353beabd7bcd2bd615b0000024d212e45000000003030303836356400c9cfbaa3b9fac6f3b6ef00000254cab144000000003030303836376400b8dbd6d0d0a1c6f337b60100029c322745000000003030303836396400484bd2f8d0d000009999000002d0bd9245000000003030303838386400c9cfd6a4cad5d2e6cc48220002bb278e45000000003030303839316400d0c2d0cbd7dbd6b860131a0002aed9f444000000003030303930316400d0a1bfb5d6b8cafd0e850500029a40c545000000003030303930336400d6d0d6a441313030468f050002cd238b45000000003030303930356400d6d0d6a435303000795b0b000210d5f645000000003030303930366400d6d0d6a4383030003a91170002ca91a045000000003030303931336400333030d2bdd2a900f54a000002eeadfc45000000003030303931346400333030bdf0c8da005bda0200027da5bc45000000003030303932386400d6d0d6a4c4dcd4b4b62901000289fa5845000000003030303933326400d6d0d6a4cffbb7d1657a000002166e6046000000003030303933336400d6d0d6a4d2bdd2a9e8b7000002ea1cfd45000000003030303933346400d6d0d6a4bdf0c8dae0c703000211bbb045000000003030303933356400d6d0d6a4d0c5cfa29b96020002227ac745000000003030303937346400383030bdf0c8da00cf72030002c6b4c645000000003030303938326400353030b5c8c8a800795b0b0002c0e61346b42b13253030303938366400c8abd6b8c4dcd4b44d66020002d2f42d4500005d0d3030303938376400c8abd6b8b2c4c1cf6e7e050002c3fbaa45000000003030303938396400c8abd6b8bfc9d1a1296801000209ce9f45000000003030303939316400c8abd6b8d2bdd2a99b2c010002be420846000000003030303939326400c8abd6b8bdf0c8daff90040002fc17a945000000003030303939336400c8abd6b8d0c5cfa2b91f0300025e7f0546000000003838383838306400d0c2b1ead7bcc8af00000000020000803f000000003838303030316400d7dccad0d6b500008ce74a0002719a2d46000000003838303030326400c1f7cda8cad0d6b58ce74a000248b31c46000000003838303030376400bbeeb3efcad0d6b58ce74a0002b804a145000000003838303030336400c6bdbef9b9c9bcdb8ce74a0002713de441000000003838303030346400b3c9bdbbbef9bcdb8ce74a0002b81e8f41000000003838303030356400d5c7b5f8bcd2cafd8ce74a000200002c45000000003838303030366400cda3b0e5bcd2cafd8ce74a000200007442000000003838303030386400c8aba3c1b5c8c8a88ce74a00029a21bc44000000003838303030396400c8aba3c1d6d0cebb8ce74a000271f59844000000003838303031316400d6f7b0e5d7dcd6b546273c00027ba6fc45000000003838303031326400d6f7b0e5c1f7cda846273c0002b840ec45000000003838303031376400d6f7b0e5bbeeb3ef46273c00028fe25f45000000003838303031336400d6f7b0e5c6bdbef946273c0002d7a39a41000000003838303031346400d6f7b0e5bef9bcdb46273c000248e15e41000000003838303031356400d6f7b0e5d5c7b5f846273c000200c0c744000000003838303031366400d6f7b0e5cda3b0e546273c000200006c42000000003838303031386400d6f7b0e5b5c8c8a846273c0002b89eae44000000003838303031396400d6f7b0e5d6d0cebb46273c0002aedf9244000000003838303033316400b4b4d2b5d7dcd6b51be70b00027135e644000000003838303033326400b4b4d2b5c1f7cda81be70b00025ca7bb44000000003838303033376400b4b4d2b5bbeeb3ef1be70b0002cd4c8044000000003838303033336400b4b4d2b5c6bdbef91be70b000252b80a42000000003838303033346400b4b4d2b5bef9bcdb1be70b00020000e441000000003838303033356400b4b4d2b5d5c7b5f81be70b000200802e44000000003838303033366400b4b4d2b5cda3b0e51be70b000200000040000000003838303033386400b4b4d2b5b5c8c8a81be70b00025210bd44000000003838303033396400b4b4d2b5d6d0cebb1be70b00028f3a9644000000003838303034316400bfc6b4b4d7dcd6b5726f02000252d08944000000003838303034326400bfc6b4b4c1f7cda8726f0200025c7f6544000000003838303034376400bfc6b4b4bbeeb3ef726f0200029a690044000000003838303034336400bfc6b4b4c6bdbef9726f0200028fc28242000000003838303034346400bfc6b4b4bef9bcdb726f020002b81e6542000000003838303034356400bfc6b4b4d5c7b5f8726f02000200009843000000003838303034366400bfc6b4b4cda3b0e5726f0200020ad7233c000000003838303034386400bfc6b4b4b5c8c8a8726f020002d7eba544000000003838303034396400bfc6b4b4d6d0cebb726f0200020a477d44000000003838303037316400b1b1d6a4d7dcd6b5b769000002713da342000000003838303037376400b1b1d6a4bbeeb3efb769000002b81ef341000000003838303037336400b1b1d6a4c6bdbef9b769000002b81ebb41000000003838303037346400b1b1d6a4bef9bcdbb7690000020000aa41000000003838303037356400b1b1d6a4d5c7b5f8b76900000200001943000000003838303037366400b1b1d6a4cda3b0e5b7690000020ad7233c000000003838303037386400b1b1d6a4b5c8c8a8b769000002ec71f544000000003838303037396400b1b1d6a4d6d0cebbb76900000271f5cd44000000003838303039366400455446b5c8c8a800becc670002141e72440000000038383030393764005245495473000000c410000002ae479940000000003838303039386400bfc9d7aad5ae00005f940200020a971c43000000003838303039396400cda8d3c3bbd8b9ba08dca5000200400a43000000003838303038316400c2d6b6afc7f7cac666070000024869bb44000000003838303038326400b0e5bfe9c7f7cac6f6740000021f450944000000003838303230316400badac1fabdad0000024a0100027b046744000000003838303230326400d0c2bdaeb0e5bfe951ea01000233cb8c44000000003838303230336400bcaac1d6b0e5bfe9cad800000266766144000000003838303230346400b8cacbe0b0e5bfe994c500000266feae44000000003838303230356400c1c9c4feb0e5bfe9751a010002148e7b44000000003838303230366400c7e0baa3b0e5bfe98e350000021f95f444000000003838303230376400b1b1bea9b0e5bfe917580a000248210345000000003838303230386400c9c2cef7b0e5bfe96327010002b8020445000000003838303230396400ccecbdf2b0e5bfe9a243010002ec89ca44000000003838303231306400b9e3cef7b0e5bfe9a9ad000002f6908344000000003838303231316400bad3b1b1b0e5bfe9d1370100023303a044000000003838303231326400b9e3b6abb0e5bfe997f304000248513045000000003838303231336400bad3c4cfb0e5bfe9d6d1010002e142e944000000003838303231346400c4fecfc4b0e5bfe9544900000200308d44000000003838303231356400c9bdb6abb0e5bfe9fcff03000200881945000000003838303231366400c9cfbaa3b0e5bfe9da45050002aec7e744000000003838303231376400c9bdcef7b0e5bfe96e550100028f127b44000000003838303231386400c9eedbdab0e5bfe9481f050002f64c4545000000003838303231396400bafeb1b1b0e5bfe94d1c0200026616ed44000000003838303232306400b8a3bda8b0e5bfe96ecb0200023d9e7545000000003838303232316400bafec4cfb0e5bfe983a6010002f6f0b044000000003838303232326400bdadcef7b0e5bfe98e20010002338bd144000000003838303232336400cbc4b4a8b0e5bfe9f40a02000233f32845000000003838303232346400b0b2bbd5b0e5bfe9b7f9010002cdfcee44000000003838303232356400d6d8c7ecb0e5bfe9f73d010002b886dd44000000003838303232366400bdadcbd5b0e5bfe9e6b80700023d621545000000003838303232376400d4c6c4cfb0e5bfe9e5960000023333c044000000003838303232386400d5e3bdadb0e5bfe91d030700029a091d45000000003838303232396400b9f3d6ddb0e5bfe9238f00000266a8f145000000003838303233306400baa3c4cfb0e5bfe995f7000002290c6a44000000003838303233316400cef7b2d8b0e5bfe9f32d000002e1da9144000000003838303233326400c4dac3c9b0e5bfe9e259010002004c2d45000000003838303330316400c3baccbf0000000085c50000025c37ee44000000003838303330326400c3baccbfbfaab2c95c870000020a8f0545000000003838303330336400bdb9ccbfbcd3b9a4293e000002854bc143000000003838303330356400b5e7c1a600000000ca8404000200dc1045000000003838303330366400cbaec1a6b7a2b5e7e29d000002ae8b5245000000003838303330376400bbf0c1a6b7a2b5e775ef0100029af9dd44000000003838303330386400d0c2d0cdb5e7c1a672f701000252b0a144000000003838303331306400caafd3cd000000008ddf0100025c17c544000000003838303331316400caafd3cdbfaab2c9d8850100028503c544000000003838303331326400caafd3cdbcd3b9a4c74c0000023373c544000000003838303331336400caafd3cdc3b3d2d7ed0c000002e1f2a344000000003838303331386400b8d6ccfa00000000970a020002e14a8944000000003838303331396400c6d5b8d600000000e68b0100025c0f7444000000003838303332306400ccd8d6d6b8d60000d91a0000023d3aea44000000003838303332316400b8d6bcd3b9a40000d7630000021f35b144000000003838303332346400d3d0c9ab00000000008f030002ae47ec44000000003838303332356400cdad0000000000006391000002cd6cd644000000003838303332366400c2c10000000000004107010002d7d3df44000000003838303332376400c7a6d0bf00000000964600000248f19144000000003838303332386400bbc6bdf0000000002c420000021f793045000000003838303332396400d0a1bdf0caf40000996d01000285ef0045000000003838303333306400bbafcfcb000000005dab00000229402145000000003838303333356400bbafb9a400000000a44e0500025c031245000000003838303333366400bbafb9a4d4adc1cfd026030002d79f2345000000003838303333376400c5a9d2a9bbafb7cac20d0100021f450545000000003838303333386400cbdcc1cf0000000002cd00000271990645000000003838303333396400cff0bdba000000003f1b00000233338744000000003838303334306400c8bec1cfcdbfc1cfce31000002c3dd2d45000000003838303334346400bda8b2c400000000f9fe000002c3cdc644000000003838303334356400ccd5b4c900000000590b00000252d81945000000003838303334366400cbaec4e000000000793500000266667e44000000003838303334376400b2a3c1a700000000b78c000002c3913345000000003838303334386400c6e4cbfbbda8b2c46e310000021f7dec44000000003838303335306400d4ecd6bd000000004770000002ec11b544000000003838303335316400bff3ceefd6c6c6b70949000002e12e0e45000000003838303335356400c8d5d3c3bbafb9a4d9190000027b349044000000003838303336306400c5a9c1d6c4c1d3e690780100022984e244000000003838303336316400d6d6d6b2d2b500004353000002299cba44000000003838303336326400d3e6d2b500000000031a0000023dcacd43000000003838303336336400c1d6d2b500000000b43a000002cd4c0945000000003838303336346400cbc7c1cf0000000003410000027bf04545000000003838303336366400c5a9d2b5d7dbbacf918f00000252b8c344000000003838303336376400b7c4d6afb7fecacea3b2000002a4108944000000003838303336386400b7c4d6af000000002a3f0000025cefa544000000003838303336396400b7fecace000000007873000002d7037f44000000003838303337326400cab3c6b7d2fbc1cf72cf00000252602545000000003838303337336400c8e9d6c6c6b70000211e00000229206445000000003838303337346400c8edd2fbc1cf0000e40a0000028ff2e844000000003838303337356400cab3c6b7000000006ca6000002f6200e45000000003838303338306400c4f0bec600000000302f000002d719aa45000000003838303338316400b0d7bec60000000014130000025cf9d945000000003838303338326400c6a1bec600000000d9120000025230b644000000003838303338336400baecbbc6bec60000420900000233d32244000000003838303338376400bcd2d3c3b5e7c6f7c7c00000029a8f8b45000000003838303339306400c6fbb3b5c0e00000476c020002c34d2845000000003838303339316400c6fbb3b5d5fbb3b56b6e0000021f812845000000003838303339326400c6fbb3b5c5e4bcfe2fd7010002853b3e45000000003838303339336400c6fbb3b5b7fecef1e20d0000023d4abb43000000003838303339346400c4a6cdd0b3b50000ca180000027165d044000000003838303339386400d2bdc1c6b1a3bda10e0a010002f6943e45000000003838303339396400bcd2bed3d3c3c6b7604a0000023dca2345000000003838303430306400d2bdd2a900000000ffff0300021fd50a45000000003838303430316400bbafd1a7d6c6d2a929450200027b242445000000003838303430326400c9faceefd6c6d2a913cc000002ae431945000000003838303430336400d6d0b3c9d2a90000c2ee00000214eecc44000000003838303430366400c9ccd2b5c1accbf852b3010002f6e84444000000003838303430376400b0d9bbf500000000375d000002b8de4244000000003838303430386400b3accad0c1accbf8e01a0000025cef3044000000003838303430396400b5e7c6f7c1accbf88809000002f6a88143000000003838303431306400d2bdd2a9c9ccd2b546eb000002ae2fb044000000003838303431316400c6e4cbfbc9ccd2b5c8300000021fa5ca43000000003838303431326400c9ccc6b7b3c70000bc0c0000025c27a144000000003838303431336400c5fab7a2d2b50000e6080000020a675244000000003838303431346400c9ccc3b3b4fac0ed2223000002aed77244000000003838303431386400b4abc3bdd3e9c0d69ee20000021fbd9244000000003838303431396400b3f6b0e6d2b50000783f0000029a89c944000000003838303432306400d3b0cad3d2f4cff125a300000252908244000000003838303432316400b9e3b8e6b0fcd7b06ffe0000020010e044000000003838303432326400cec4bdccd0ddcfd0ac700000020aafb344000000003838303432336400bec6b5eab2cdd2fb63140000027b747444000000003838303432346400c2c3d3ce00000000a635000002d733c045000000003838303432356400c2c3d3ceb7fecef13814000002719d3545000000003838303432366400c2c3d3cebeb0b5e36d210000020aaf9344000000003838303433306400babdbfd500000000e76100000248310d45000000003838303433316400b4acb2b000000000892e0000023d2a6544000000003838303433326400d4cbcae4c9e8b1b88988000002295cc044000000003838303433376400cda8d3c3bbfad0b5fae2000002e10e2845000000003838303433386400bbfab4b2d6c6d4ec04250000023dca7e44000000003838303433396400bbfad0b5bbf9bcfef5bd000002e1ba4645000000003838303434306400b9a4d2b5bbfad0b52c3802000200e03545000000003838303434316400bbafb9a4bbfad0b5b923000002ec151a45000000003838303434326400c7e1b9a4bbfad0b55a0c000002719dfa44000000003838303434336400b7c4d6afbbfad0b5622500000233434544000000003838303434346400c5a9d3c3bbfad0b59013000002664ebc44000000003838303434356400d7a8d3c3bbfad0b525cf01000252448145000000003838303434366400b5e7c6f8c9e8b1b8180d060002140e0a45000000003838303434376400b9a4b3ccbbfad0b56e9900000229ccb044000000003838303434386400b5e7c6f7d2c7b1ed976c0000025260a545000000003838303435326400b5e7d0c5d4cbd3aa472b0000020a3fa244000000003838303435336400b9abb9b2bdbbcda86709000002d7db8f44000000003838303435346400cbaecef100000000ab250000022944a344000000003838303435356400b9a9c6f8b9a9c8c8eb9c000002a4e07344000000003838303435366400bbb7beb3b1a3bba4f2240100025cf7b844000000003838303435396400d4cbcae4b7fecef1a2b10100027195a444000000003838303436306400ccfac2b700000000023700000229d49644000000003838303436316400cbaed4cb00000000ccf80000020aa31945000000003838303436326400bfd5d4cb000000000d800000025c0f3c44000000003838303436336400b9abc2b700000000c5010000021fa55944000000003838303436346400b2d6b4a2ceefc1f7deb70000024841ee44000000003838303436356400bdbbcda8c9e8caa9779300000248d9e344000000003838303436366400c2b7c7c5000000008b2c000002e1420f45000000003838303436376400bbfab3a100000000e00f000002cddced44000000003838303436386400b8dbbfda000000000b5700000285ebd544000000003838303437316400d2f8d0d00000000061e701000214ca5045000000003838303437326400d6a4c8af000000003f40010002a420ba44000000003838303437336400b1a3cfd500000000cb1e00000200841a45000000003838303437346400b6e0d4aabdf0c8dafec6000002d7dbb644000000003838303437366400bda8d6fe00000000bf960200021fedb744000000003838303437376400bda8d6feb9a4b3ccdc64020002661ebd44000000003838303437386400d7b0d0ded7b0cacee231000002d7939e44000000003838303438326400b7bfb5d8b2fa0000b8a10100025c0f6644000000003838303438336400c8abb9fab5d8b2fad4a9000002290c4244000000003838303438346400c7f8d3f2b5d8b2fa40a8000002a4d06244000000003838303438356400d4b0c7f8bfaab7a24b2d0000024801c644000000003838303438366400b7bfb2fab7fecef1582200000252f86b440000000038383034383964004954c9e8b1b80000219d000002d78f0745000000003838303439306400cda8d0c5c9e8b1b8505c02000200c4a245000000003838303439316400b0ebb5bccce50000d1c1010002f6c08645000000003838303439326400d4aac6f7bcfe00006808040002c3938245000000003838303439336400c8edbcfeb7fecef18df3020002d7c32f45000000003838303439346400bba5c1aacdf80000048701000285d33245000000003838303439376400d7dbbacfc0e00000d2550000025c8fd844000000003838303530316400baac48b9c900000066db060002aebf0d45000000003838303530326400baac42b9c9000000278f010002c315a344000000003838303530356400cfa1c8b1d7cad4b490e7010002f600b1440000000038383035303664003547b8c5c4ee0000c0e807000214b65145000000003838303530376400b9fab7c0befcb9a4492208000271110a45000000003838303531336400baa3cfbfcef7b0b6c1b1020002e1da1245000000003838303531356400cda8b4efd0c538380f04030002c38d2d450000000038383035313664005354b0e5bfe90000264701000233d3a244000000003838303531396400ccbcd6d0bacd0000029b060002cdacef44000000003838303532306400d6c7c4dcb5e7cdf8aed8040002e18a5645000000003838303532316400bbc6bdf0b8c5c4ee862e0200020a67e044000000003838303532326400b5cdbfd5beadbcc308d80600027b4ce744000000003838303532336400cdadc0c2b8dfcbd9abf90000021fc11945000000003838303532346400baacbfc9d7aad5ae65720400020060d144000000003838303532356400b8dfccfa00000000f11a0300021f15b944000000003838303532366400b8dfb7d6baecb9c9743b0300021f55a844000000003838303532376400b3d0c5b5b2bbbcf579ee000002b85eed44000000003838303532386400befcb9a4d0c5cfa2c03e0100028f4ad444000000003838303532396400b4ced0c2b9c90000ef5c00000233035e44000000003838303533306400bacfb3c9c9faceef70e6010002f620a544000000003838303533316400b5cdb0b2c8abb7d6e722080002aeffbb44000000003838303533326400d5fbcce5c9cfcad029ba020002ecd1e844000000003838303533336400ceefc1aacdf800003b160700021fe91245000000003838303533346400efaeb5e7b3d8b8c5891d0a000266264d45000000003838303533356400cfa1cdc1d3c0b4c5ee69020002b8dea144000000003838303533366400cea2c5ccbeabd1a1afb1000002714d0e45000000003838303533376400bacbb5e7bacbc4dcc9070700023d62f144000000003838303533386400b2ceb9c9bdf0c8da7b910400029a81e744000000003838303533396400b9c9c8a8bca4c0f8f4d1000002338b7645000000003838303534306400b4b4cdb6b8c5c4eea88b080002142ef4440000000038383035343164004149cad6bbfa5043561b0100023d8ae544000000003838303534326400cbaec0fbbda8c9e8f2c1040002cdbcdd44000000003838303534336400cde2d7cab1b3beb0804c0000027b068545000000003838303534346400b9e2b7fc00000000374f0f0002a42c7345000000003838303534356400d4c6bcc6cbe300002c5e040002ae4b4b45000000003838303534366400cec0d0c7b5bcbabd88d9030002331b6245000000003838303534376400b2a3c1a7bbf9b0e52f44000002ae27fe44000000003838303534386400c9ccd2b5babdcceca1ae0700029ac10645000000003838303534396400bfc9c8bcb1f90000d9e40000020ab30e45000000003838303535306400504342b8c5c4ee00d6c1020002c3a52745000000003838303535316400b4f3bbf9bdf0b3d670b100000214260945000000003838303535326400b3b5c1aacdf8000099290300028f5ac344000000003838303535336400d2b3d1d2c6f80000cffd010002660a0e45000000003838303535346400bfc6b4b4b0e5b4ce610b000002b8768744000000003838303535356400b2c6cbb0cafdd7d6f3a4000002d77bd744000000003838303535366400d7f25354c1acb0e53a0f0000020a4f7945000018253838303535376400c9faceefd2dfc3e7781c0100021f194345000000003838303535386400bddac4dcbbb7b1a3379e0400023d1a6345000000003838303535396400d2aad4bccad5b9babb2200000214056a46000000003838303536306400b8dfb6cbd7b0b1b89c75050002a4a42b45000000003838303536316400d5dbb5fec6c1000054580200029a3d1245000000003838303536326400b8dfd0a3b1b3beb075950000027bcc4d45000000003838303536336400cab3c6b7b0b2c8aba6ac00000252d04945000000003838303536346400b0d7bec6b8c5c4eeaf9900000200f6d445000000003838303536356400cbcdd7aac7b1c1a61b5f0000028f314f460000000038383035363664004149d1dbbeb5000076b7020002c3f90b45000000003838303536376400baa3c4cfd7d4c3b3c3b9010002ec4d8845000000003838303536386400c9faceefd6cac4dcdc1e0100029a29e2440000000038383035363964003344b4f2d3a100000c880100025c5b7945000000003838303537306400b8dfd3a6cad5bfeed55f0900020a4fa244000000003838303537316400ccbccfcbceac0000cf040100020aef2045000000003838303537326400d0c2c1e3cadb0000e6e8030002a460a544000000003838303537336400d5aac3b1000000005ae801000229100945000000003838303537346400c6bbb9fbb8c5c4ee6452020002ec31d245000000003838303537356400b5d8c8c8c4dc0000ed7900000285573245000000003838303537366400b2a2b9bad6d8d7e96f300200029a152745000000003838303537376400b0b2b7c0b7fecef103c00100021f83b045000000003838303537386400d7a8cfeeb4fbbfee7f770a00028f62c244000000003838303537396400d6c7c6d7414900009a2a010002f600a444000000003838303538306400d6c7c4dcbdbbcda8ba2f020002cdf68445000000003838303538316400bfd8d6c6c8a8b1e4ad0d0200027145b944000000003838303538326400b7e7b5e700000000a2750b00020a7f5345000000003838303538336400b3e4b5e7d7ae00009650060002334ba645000000003838303538346400caafc4abcfa90000125f0200023d621345000000003838303538356400b7e7c9b3d6cec0ed8a5600000214469644000000003838303538366400cdc1b5d8c1f7d7aa2dff000002296cb044000000003838303538376400bedbb0b1f5a50000877900000200d6af45000000003838303538396400d6c7c4dcb4a9b4f7ff9603000233e33b45000000003838303539306400cdf8c2e7d3cecfb7914402000214f6bf44000000003838303539316400c9cfbaa3d7d4c3b3b0ba010002858b2745000000003838303539326400bba5c1aabdf0c8da1fc2020002a4384345000000003838303539336400d3a4cdafb8c5c4ee95f4010002f6f82e45000000003838303539346400d2bbb4f8d2bbc2b77e90100002b8524045000000003838303539366400cce5d3fdb8c5c4ee18c4010002ec51de44000000003838303539376400d1f8c0cfb8c5c4eeeb11030002298cc444000000003838303539386400b2a9b2cab8c5c4eef454000002e1d22845000000003838303539396400c3f1d3aad2bdd4ba905b02000252c00a45000000003838303630316400d6c7bbdbd5fecef1387b0200027b3cb944000000003838303630326400c3e2cbb0b8c5c4eee40101000248599744000000003838303630336400d0c2bdf8d6b8b1eabc81000002cdc48a4400000000383830363034640050564446b8c5c4eeac6900000248b1b644000000003838303630356400d7b0c5e4cabdbda8876f01000248f9a544000000003838303630366400b8a8d6fac9fad6b3c82f0100023dba8544000000003838303630376400b6abcafdcef7cbe34d9108000229e4e444000000003838303630386400b5dac8fdb4fab0eb3976020002f6c8c244000000003838303630396400bfe7beb3d6a7b8b667390200020a87c044000000003838303631306400d6d0b6edc3b3d2d7ce150200023deabb44000000003838303631316400bacbcedbc8beb7c0c82001000248c1b344000000003838303631326400c4f8bdf0caf40000ef7c010002ae27b044000000003838303631336400b5e7d7d3c9edb7dd655b000002141eaa44000000003838303631346400c2ccc9abbda8d6fe281a01000266a69e44000000003838303631356400bcd2cda5d2bdc9fa6c740000025cc79844000000003838303631366400b4f3b7c9bbfa0000386402000248b1cf440000000038383036313764004950beadbcc300009d500200028faa9244000000003838303631386400bbafb7cab8c5c4eea694010002a4988e44000000003838303631396400d2b5bca8d4a4d4f6866d000002d7fb1445000000003838303632306400c8afc9ccbdf0b9c92c0b01000285638e440000000038383036323164004e4654b8c5c4ee005272010002c385a644000000003838303632326400c6c6d4f6b7a2bcdbae940000029a09d544000000003838303632336400b8ced1d7b8c5c4ee5ff401000285e39e44000000003838303632346400d0c2d0cdb3c7d5f25f5b03000200489544000000003838303632356400d6f7d3aab1e4b8fc8fc5000002b8ae7644000000003838303632366400c1b8cab3b8c5c4eea1c3000002ec515f44000000003838303632376400b3acc1d9bde7b7a284810300020a1fca44000000003838303632386400b7b0b5e7b3d80000838201000229ecb2440000000038383036323964004d6963726f4c45445cbb010002d76bdc44000000003838303633306400d0e9c4e2b5e7b3a7bff80200025c4fcb44000000003838303633316400d2bbcce5d1b9d6fd3a7e00000229dc9344000000003838303633326400b6afc1a6b5e7b3d825c8010002b8c68444000000003838303633336400c6fbb3b5c8c8b9dc73200100023d3aeb44000000003838303633346400baac474452000000758c00000233cb8844000000003838303633356400cfc8bdf8b7e2d7b01702020002c3fdf344000000003838303633366400c8c8b1c3b8c5c4ee82f6000002d783c744000000003838303633376400454441b8c5c4ee00873c000002718d9e44000000003838303633386400544f50436f6eb5e72e74010002293c5f44000000003838303633396400b9e2c8c8b7a2b5e789080100023d628e44000000003838303634306400c0facab7d0c2b8dfedaf000002cdc41145000000003838303634316400c0facab7d0c2b5cd56080000021fc50843000000003838303634326400b9a9cffac9e70000b86a000002e1829a4400000000383830363433640057656233b8c5c4ee984c010002cddcdd440000000038383036343464004452472d444950004738000002ecf1974400000000383830363435640041494743b8c5c4ee064e050002297cf944000000003838303634366400b8b4bacfcdadb2ada93e0100020a0fd144000000003838303634376400cafdbeddc8b7c8a826bf000002e14abf44000000003838303634386400cbbdc4bcd0c2bdf844a400000200009944000000003838303634396400504f45bdbac4a400dc6e00000266f67344000000003838303635306400d1aad1f5d2c70000ef48000002ae27b744000000003838303635316400c2c3d3ceb8c5c4eeec43020002d753a344000000003838303635326400b4b4d0c2d2a900005e2e0400027bfc9744000000003838303635336400cbbdc4bcd6d8b2d63ee702000252f8aa4400000000383830363534640043686174475054b84c540200020a77de44000000003838303635356400b8c6eed1bff3b5e78bab0200023d02874400000000383830363536640043504fb8c5c4ee008124030002488f9d45000000003838303635376400cafdd7d6cbaed3a1bf9b000002b8569a44000000003838303635386400b8dfd1b9bfecb3e48e340100026676c944000000003838303635396400bac1c3d7b2a8c0d7f19a0100023d22f244000000003838303636306400b9a4d2b5c8edbcfecc40000002ecb1a1440000000038383036363164003647b8c5c4ee0000172202000271ad0f45000000003838303636326400cab1bfd5b4f3cafd1d9f000002ec51b344000000003838303636346400bbfac6f7cad3bef5cb10020002713dd144000000003838303636356400d7f25354cad7b0e55f10000002859f4345000018253838303636366400bfc9bfd8bacbbedb890a03000285cf0e45000000003838303636376400cafdbeddd2aacbd80d4b050002cd9c9044000000003838303636386400d6aacab6b8b6b7d19335000002850b9744000000003838303636396400cbe3c1a6d7e2c1de91ff0400023333ad44000000003838303637306400b9e2cda8d0c50000b32c040002ec4d2145000000003838303637316400d6d0ccd8b9c00000879005000266ce9844000000003838303637326400b4e6b4a2d0bec6acc2300200028fda0d45000000003838303637336400bbecbacfcfd6cab5b3ca0000023d1ad844000000003838303637346400d3a2ceb0b4efb8c5268e010002f600e944000000003838303637356400bcf5cbd9c6f70000a52e010002c3b5f144000000003838303637366400bbeed4be4554460091f43d00028feaa544000000003838303637376400bbeed4bebfc9d7aaa97b0100021f151244000000003838303637386400c2bdb9c9cda8d6d83bc80100029ac18f44000000003838303637396400d6dcc6dab9c900007bbd09000248019f44000000003838303638306400b7c7d6dcc6dab9c9b7f80c0002cdb49d44000000003838303638316400bcf5b7cad2a90000b4d100000233239d44000000003838303638326400bbaaceaabaa3cbbc79d70000029a89d644000000003838303638336400d0c7c9c1b8c5c4ee639600000271ada6440000000038383036383464004243b5e7b3d800003d1c010002f6209b44000000003838303638356400d2bac0e4b7fecef18ea80300027ba41145000000003838303638366400bbaaceaac6fbb3b568f40100020a5fd344000000003838303638376400bbeed4bed0a1c5cc818b0100025ccfca44000000003838303638386400d0c2d0cdb9a4d2b58a3502000271adc944000000003838303638396400bbaaceaacbe3c1a66c78010002b86eb744000000003838303639306400d7f2c8d5c7bfcac660ca010002b89eec420000ab233838303639316400d7f2c8d5c8f5cac69a72010002f6e8f143000060243838303639326400b6ccbee7d3cecfb7c5380200020060a144000000003838303639336400b6e0c4a3ccac4149f04b0200025c87a444000000003838303639346400bbeed4bed0a1c5cc92b903000248d198440000000038383036393564005045454bb2c4c1cfe95c00000285e3f144000000003838303639366400d0a1c3d7c6fbb3b56a3f010002cd5cce44000000003838303639376400b7c9d0d0c6fbb3b53d2d010002cdb4e144000000003838303639386400bfedbbf9455446005ca819000285bbcf44000000003838303639396400d7eebdfcc7e9d0f762db0c000214fe0645000000003838303730316400536f7261b8c5c4ee4706010002a410f044000000003838303730326400bfc7d7cad4b40000e48000000233671945000000003838303730336400c8cbd0cebbfac6f7770e04000200640a45000000003838303730346400b9a4d2b5b4f3c2e9d32e010002e10a7044000000003838303730356400c7e2c4dcd4b400002638080002b8eee544000000003838303730366400b7d6c9a2c8bec1cf792e000002cdac4c44000000003838303730376400b3e8ceefbeadbcc332d200000248c9a444000000003838303730386400cca8d7cab1b3beb0bb7d000002cd0c5c45000000003838303730396400c8cbd4ecc8e200001b53000002ae0fa344000000003838303731306400d6d6d2b500000000133b000002c33dcb44000000003838303731316400b2d9d7f7cfb5cdb3faf7000002c32daf44000000003838303731326400cea2d0a1c5ccb9c9fdf3020002295cd744000000003838303731336400455443b8c5c4ee00479b0000028f9a0045000000003838303731346400b7fab8c5c4ee00009aa1010002e12e7145000000003838303731356400c1d7b8c5c4ee0000b76d010002006c3645000000003838303731366400b9e2bfccbbfa0000bd030100021f2d604500000000383830373137640043324db8c5c4ee00a85200000271b10045000000003838303731386400d0a1baeccae9b8c5e05d010002d753a144000000003838303731396400b5d8ccafbeadbcc3aa610000020a970645000000003838303732306400b6b6d2f4b8c5c4eebe3f040002aebf9644000000003838303732316400b1b1c9cfd6d8b2d6dd610800028f528344000000003838303732326400bbaaceaabae8c3c9bf1f030002f630b444000000003838303732336400b7a2bfc9d7aad5aeb86c000002710d7f44000000003838303732346400b5d8cfc2b9dccdf862600100025c2fa8440000000038383037323564004d696e694c454400850a0200029a999b440000000038383037323664004d4355d0bec6ac0001d5000002e1e2a244000000003838303732376400d1cebafecce1efaee4e6000002ae37a944000000003838303732386400babdd4cbb8c5c4ee7827020002e1f2d64400000000383830373239640043584fb8c5c4ee006ec2000002e14a6244000000003838303733306400b4a2c4dc000000009814110002aee7e144000000003838303733316400d0c2b2c4c1cf0000f8a80500024881d0440000000038383037333264004149d6c7c4dccce59d72060002299ca044000000003838303733336400c8cbc4d4b9a4b3ccf3450100029ab9df44000000003838303733346400b9a4d2b5c6f8cce52677000002c3eda644000000003838303733356400d7a8beabccd8d0c2fd35060002d75b8144000000003838303733366400b9a4d2b5c4b8bbfaf90b0100020a9fe944000000003838303733376400484a54b5e7b3d8000a5c01000233c39d44000000003838303733386400cafdd7d6c2cfc9fa9449020002d713e144000000003838303733396400b1dfd4b5bcc6cbe3792b020002ec39e144000000003838303734306400d0c2d0cdd1ccb2ddf9ed0000028f42ce44000000003838303734316400b4faccc7b8c5c4eea358000002143e9444000000003838303734326400b9ccccacb5e7b3d86150040002aeefa344000000003838303734336400ceefd2b5b9dcc0edbd7e0300028f729b44000000003838303734346400c6fbb3b5b2f0bde222e30000029a79b2440000000038383037343564004e4d4eb8c5c4ee009b86000002290ccc44000000003838303734366400b9fad7cad4c60000123e010002ae07da440000000038383037343764004149d2bdc1c6b8c5017b010002e17a9a44000000003838303734386400d4aad3eed6e6b8c59188030002e172fa44000000003838303734396400d4c6d3cecfb70000dece0000020a8feb44000000003838303735306400ccecc8bbc6f800009d650300023dbab944000000003838303735316400d7f2c8d5b5f8cda3638d000002ecd13b43000018253838303735326400d7f2d4f8b5f8cda3fcb9000002cd4c5343000060243838303735336400c2ccc9abb5e7c1a610820c000271cd9c44000000003838303735346400c5e0d3fdd7eacaafd23900000233fbd544000000003838303735356400c4c6b5e7b3d80000842602000252c88944000000003838303735366400bbfab9b9cefcb3ef5a65000002c3157344000000003838303735376400c0e4c1b4ceefc1f79272020002297cb144000000003838303735386400c6fbb3b5d0bec6acc95f01000271b58844000000003838303735396400bbbbb5e7b8c5c4ee02fa000002c31d9444000000003838303736306400d4a4d6c6b2cb0000053501000200a08a44000000003838303736316400efaebff300000000976f01000200989544000000003838303736326400d0c5b4b4000000009b44030002c3bdc344000000003838303736336400d7d4d3c9cfd6bdf051030300021f5dad44000000003838303736346400bca6c8e200000000f0450000028fd25b44000000003838303736356400baa3d1f3beadbcc3e82c0100020ac7a044000000003838303736366400d3c4c3c5c2ddb8cb50190100020af77444000000003838303736376400b5e7d7d3d6bd000047b6000002851b9f44000000003838303736396400b9c9c8a8bcafd6d0cb4e0100025c6fc244000000003838303737306400d7f2c8d5c9cfb0f175940300024817e0450000000038383037373164004d534349d6d0c5cccb11040002e1f2cc44000000003838303737346400d7f2c8d5cad7b0e59cc3020002c3f51345000018253838303737386400b4ced0c2d4a4d4f67002000002e1eae144000000003838303737396400b8dfc8dad7cac5ccfab1000002c345d744000000003838303738306400c8dad7cad4f6bcd3622c010002b8de2a4300000000383830373831640051464949d0c2bdf88d910100028f7e1145000000003838303738326400b1a3cfd5d0c2bdf8e7740000025260a444000000003838303738336400c9e7b1a3d0c2bdf84afc000002144e3a45000000003838303738346400d7f2c8d5bdcfc8f57451020002482156430000f1223838303738356400d7eebdfcb6e0b0e5cf1b05000248738246000000003838303738366400baa3cde2d2b5cef1a045030002b8a61e45000000003838303738376400b8dfc9ccd3fe0000e02f0000020ac75c44000000003838303738396400d7f2b3c9bdbb3230fd6e0100027b540444000000003838303739306400b8dfb8bad5aec2ca0bdb02000229749a44000000003838303739316400cdf8baecbeadbcc37aa8010002cd5c8944000000003838303739326400bbf9bdf0d4f6b2d684ac0000022994af44000000003838303739336400bbf9bdf0bcf5b2d611a3000002ec31e044000000003838303739346400d4b6b3ccb0ecb9aba76e00000252808c44000000003838303739356400bfdad5d6b7c0bba4cf5b03000271e90745000000003838303739366400d2bdb7cfb4a6c0ed2dc4000002ae178d44000000003838303739376400b3e6baa6b7c0d6ce4c420000025200bb44000000003838303739386400b3acbcb6b5e7c8dd45b90000029aa51645000000003838303739396400cafdbeddd6d0d0c4b02c0c00025220f944000000003838303830316400bbf9bdf0d6d8b2d64f680600029a050b4500000000383830383032640051464949d6d8b2d6b77f03000252ac4c45000000003838303830336400c8afc9ccd6d8b2d613c70300027bfcf544000000003838303830346400d0c5cdd0d6d8b2d6e5970000021f8d0145000000003838303830356400b1a3cfd5d6d8b2d6537b05000266fe1745000000003838303830366400c9e7b1a3d6d8b2d625c404000200443c45000000003838303830376400b9c9b6abd4f6b3d60b6e000002ecf1f544000000003838303830386400b9c9b6abbcf5b3d655e2000002aed82546000000003838303830396400bbf9bdf0b6c0c3c53f8100000214162545000000003838303831326400d7f2c8d5c1acb0e5cba600000214c8b645000018253838303831336400b2a2b9bad6d8d7e98ade0200027b9c0445000000003838303831346400c4e2d4f6b3d6000042a200000248291345000000003838303831356400c4e2bcf5b3d6000031960400024851fc44000000003838303831366400c3dcbcafb5f7d1d0029d010002ae0f1145000000003838303831376400c9ccd3febcf5d6b59fb5030002c3ad8444000000003838303831386400cda8b4efd0c5c8c8d853050002a410a343000000003838303832316400b4f3c5ccb9c90000d3e0090002aeef0345000000003838303832326400d7f2cad5bbeed4bed71d00000200e08644000000003838303832336400cea2c5ccb9c90000fec7010002f690de45000000003838303832346400b8dfcad0d3afc2caff230300029a190644000000003838303832356400d4a4bcc6d7aabff75eb4060002e1ea8044000000003838303832366400b5cdcad0d3afc2ca8c08050002b8c62a45000000003838303832376400b8dfcad0bebbc2ca2ad20300025268f744000000003838303832396400b5cdcad0bebbc2ca91a805000252fc4145000000003838303833336400bff7cbf0b9c90000aed8030002cd0c1744000000003838303833346400cea2c0fbb9c90000689604000248c9c144000000003838303833356400bca8d3c5b9c90000d880020002d7430445000000003838303833366400c5e4b9c9b9c90000fb000000026636b944000000003838303833376400bbeed4beb9c900001749060002d7b34b44000060243838303834326400d2b5bca8d4a4c9fd8a8500000271aa3846000000003838303834336400d2b5bca8d4a4bdb55f39030002717d3244000000003838303834346400d4a4bcc6c5a4bff7280b000002f6892a46000000003838303834356400b8dfb9c9cfa2b9c99dfb020002d713ac45000000003838303834366400c6c6bebbd7cab2fa09660700029aed1146000000003838303834376400d0d0d2b5c1facdb71c580500027bf03c45000000003838303834386400b1bbbed9c5c60000a4d0000002338b1f45000000003838303834396400bbd8b9babcc6bbae05da06000271e94d45000000003838303835306400b6a8d4f6d4a4b0b849ea020002f6b81145000000003838303835316400d2d1b8dfcbcdd7aa3007000002147e1044000000003838303835326400b2ceb9c9d0c2b9c99a3e0200029a7d5e45000000003838303835336400d6d0d7d6cdb70000d90b05000214be9044000000003838303835346400d4a4b8dfcbcdd7aa0908000002e1aa2344000018203838303835366400b6a8d4f6b9c90000769d0100025cdf3044000000003838303835376400d6a4bdf0bbe3bdf0da5c03000214268d44000000003838303835386400b9fabfaab3d6b9c93e8b000002c385b944000000003838303835396400d4b1b9a4b3d6b9c9991e010002338b0645000000003838303836306400bfdbb7c7bff7cbf013ba04000233d38f44000000003838303836316400c1acd0f8bff7cbf0a05e0f00020ad7a243000000003838303836336400d7f2c8d5d5c7cda31655040002cd243d45000018253838303836346400d7f2c8d5d5f1b5b4ced6040002662659430000ab233838303836356400bdfcc6dad0c2b8dfe2c60400023d82ec44000000003838303836366400bdfcc6dad0c2b5cd411c020002527812430000f1223838303836376400d7f2b8dfbbbbcad675d90500020ad70f430000f1223838303836386400b8dfb1b4cbfed6b5fdf8010002b8a6db44000000003838303836396400b9c9c8a8d7aac8c301e00700023393b844000000003838303837306400c1bdc4ead0c2b9c9952b0000027155c244000000003838303837316400b9c9c8a8b7d6c9a21cdb030002ae97a644000000003838303837326400bdfcc6dab8b4c5c65a830000025c2b984500008e1c3838303837336400b8f6c8cbb3d6b9c9568200000248918144000000003838303837346400d7f2d4f8d5c7cda374a10100026666c3420000ab233838303837356400d6d0d0a1d2f8d0d0fcaa00000266aeb444000000003838303837366400bba7cafdd4f6bcd3dfea0200027b74df43000000003838303837376400bba7cafdbcf5c9d965e500000252dc1e45000000003838303837386400b0d9d4aab9c90000982d010002f6388b44000000003838303837396400b5cdbcdbb9c90000a831070002334ba744000000003838303838306400bdfcc6dac7bfcac67f54020002c3b5af43000000003838303838316400bdfcc6dac8f5cac60656030002149e3d44000000003838303838326400bec3b2bbb7d6baec018a050002a43072440000000038383038383364004d534349b3c9b7dd311f0e00028f22e244000000003838303838346400d7eebdfcd2ecb6afdfee07000200105044000018253838303838356400bdfcb6cbb4ced0c2cc10000002b8ae01440000cf203838303838366400d7f2c8d5bdcfc7bf5360030002e17abe430000ab233838303838376400b4ced0c2b3acb5f8541700000285bb3b44000000003838303838396400b2bbbbeed4beb9c96e04000002141c9545000000003838303839306400c5e4b9c9d4a4b0b8e301000002f6c8bd44000000003838303839316400c6c6b7a2d0d0bcdb9c86010002859f0e45000000003838303839326400b8dfd6cad1bab9c97bac000002d7c34744000000003838303839336400cbcdd7aab3acb5f8fa01000002cda4c044000000003838303839346400d1f8c0cfbdf0b3d66382010002d76be444000000003838303839356400b3d6d0f8d4f6b3a43493000002d733c844000000003838303839366400b7e7cfd5cce1cabe6f1402000233336a43000000003838303839376400bcb4bdabbde2bdfb948d00000200b02444000000003838303839386400bdfcd2d1bde2bdfbf73601000229a4fc44000000003838303839396400eedcbdf0caf400003e4d01000229a4ac44000000003838303930316400d0c5cfa2b0b2c8abc5480300029abd1545000000003838303930326400ccd8cbb9c0adb8c5e7af0300021f39b545000000003838303930336400cbaeb2fac6b70000242e0000021f251e44000000003838303930346400bbfac6f7c8cbb8c5f2080d000200e2a145000000003838303930356400b3acb5bcb8c5c4eec5fd0000020a2d9745000000003838303930366400d6c7c4dcbcd2bed3eed202000229845945000000003838303930386400d6b0d2b5bdccd3fdb4e9010002a4207a44000000003838303930396400c8bcc1cfb5e7b3d8c16c03000266621845000000003838303931306400b2ddb8caeca200007a4d000002a490ff44000000003838303931316400d0dbb0b2d0c2c7f880f5040002b886cf44000000003838303931326400cde2b9c7f7c0bbfa697b0000023d229444000000003838303931336400bbf9d2f2b8c5c4ee3f9701000285173045000000003838303931346400befcc3b3b8c5c4eeca3d0000020ac79744000000003838303931356400d7f2c8d5cdbbd5c7f82300000285562d46000000003838303931366400b9fab2fac8edbcfe39f40200027bac1a45000000003838303931396400d4c1b8dbb0c40000a81b0500023d0a0a45000000003838303932306400c3e2d2dfd6cec1c621e30000029a619444000000003838303932316400b0a2c0efb8c5c4eecc4e0600021fc5df44000000003838303932326400eed1bdf0caf4000091620000023d4aeb44000000003838303932336400c8fcc2edb8c5c4ee80d8000002293c8a44000000003838303932366400c0acbbf8b7d6c0e03041010002ecc1ae44000000003838303932396400ceacc9facbd800006e920100021f6ddd44000000003838303933306400c6fbb3b5b5e7d7d36bd1040002b8162f45000000003838303933336400d6c7c4dcd2bdc1c65dcf0300023303ed44000000003838303933366400d6edc8e200000000d487000002b87eed44000000003838303933396400cedec8cbbbfa000050aa0500025cbf7844000000003838303934306400505050b8c5c4ee0074c00300027b740e44000000003838303934316400bfe7beb3b5e7c9cc4f1904000200b8b144000000003838303934326400d0e9c4e2cfd6cab52a8904000248819744000000003838303934336400c1bfd7d3bfc6bcbcae9d010002ec410045000000003838303934346400cedec8cbbcddcabbdb7f040002524037450000000038383039343564004f4c4544b8c5c4ee35fb0200029a291145000000003838303934366400c7f8bfe9c1b400006d8a05000252108644000000003838303934376400bbafd5ae414d4300736e01000229fc8544000000003838303934386400c8cbb9a4d6c7c4dca3e90e0002f668e944000000003838303934396400d6c7bbdbb3c7cad0e9fd0400020a578e44000000003838303935306400befcc3f1c8dabacfe7550300027bc4db44000000003838303935316400d0c2c4dcd4b4b3b59a680d0002143efa44000000003838303935326400d0bec6ac0000000019ec0a0002d7432e45000000003838303935336400d7e2b9bacdacc8a88a710000028f523f44000000003838303935346400b4f3cafdbedd00006feb050002336bdb44000000003838303935356400cfe7b4e5d5f1d0cbea780600025c9fd144000000003838303935366400ccdad1b6b8c5c4eee04e05000252988544000000003838303935376400b9a4d2b5bba5c1aa69ce0600027bcc0f450000000038383039353864004149d3aacffa000020800100027b945f44000000003838303935396400d6aacab6b2fac8a8d6a1000002b8568b44000000003838303936306400b7c2d6c6d2a90000c0410100028f02a144000000003838303936316400d0a1c3d7b8c5c4eee301050002cd901b45000000003838303936326400b0d9b6c8b8c5c4eeea79040002f668f044000000003838303936336400d7f2c8d5b6cfb0e5146c0000020a578943000000003838303936346400ccd8b8dfd1b900003f680300020ac76145000000003838303936356400b3acc7e5cad3c6b528f0010002cdb41545000000003838303936366400cffbb7d1b5e7d7d382fa0500020a9f1545000000003838303936376400cafdd7d6bbf5b1d2f2900100025cefeb44000000003838303936386400cca5d1b9bce0b2e2294200000229f41045000000003838303936396400cedecfdfb6fabbfada79010002a48c3345000000003838303937306400b7d6b2f0c9cfcad0de63020002ec01be44000000003838303937316400bdb5bde2cbdcc1cfd2ea0000028f829e44000000003838303937326400d1c5bdadcbaeb5e79244030002cd949d44000000003838303937336400d2bdc3c0b8c5c4ee3c77010002cd549244000000003838303937346400d1ccb2ddb8c5c4eeed7200000200a40e45000000003838303937356400d3d0bbfab9e8b8c5348c0000029a81f84400000000383830393737640042495056b8c5c4ee6f74030002b8febc44000000003838303937386400446565705365656bd37a0c00023d52ce44000000003838303937396400bfc6b4b4b3c9b3a41c4b000002d753774400000000383830393831640054445820c4dcd4b4dd290700027b640b4500000000383830393832640054445820b2c4c1cfe44b0d0002f668454500000000383830393833640054445820cffbb7d1b043030002143e644500000000383830393834640054445820bfc9d1a17d810800029a313b4500000000383830393835640054445820c9ccc3b374d60100025ca7a34400000000383830393836640054445820b7fecef1c39b0200025ce7d24400000000383830393837640054445820d6c6d4ec3f470b00023d6a564500000000383830393838640054445820b9abd3c3371c0200025258b14400000000383830393839640054445820bdbbd4cbf8fc020002b8c60a4500000000383830393930640054445820bdf0c8da6b0d04000285a7304500000000383830393931640054445820bda8c9e87738040002c355bd4400000000383830393932640054445820d0c5cfa23e3e0d000266d6ac4500000000383830393933640054445820d7dbc6f3d255000002a4881b45000000003838313030316400c3baccbf0000000085c500000233f30745000000003838313030326400c3baccbfbfaab2c95c870000023dfe1845000000003838313030336400b6afc1a6c3ba000017470000021f812b45000000003838313030346400c1b6bdb9c3ba0000444000000266d6ad44000000003838313030356400bdb9ccbfbcd3b9a4293e000002b85e0044000000003838313030366400caafd3cd0000000061df010002cd101045000000003838313030376400d3cdc6f8bfaab2c9959b0000025caf4145000000003838313030386400d3cdb7feb9a4b3cc52bc00000229acc444000000003838313030396400d3cdccefb7fecef1fc55000002e1eac444000000003838313031306400d3cdc6f8b9a4b3cc5566000002339bc744000000003838313031316400caafd3cdbbafb9a47987000002293cb744000000003838313031326400c1b6d3cdbbafb9a4ee31000002d7a3c244000000003838313031336400caafd3cdc3b3d2d7de3a00000214668f44000000003838313031346400c6e4cbfbcaafbbafac1a0000023d828144000000003838313031356400bbafb9a400000000efaf050002aee78244000000003838313031366400c8d5d3c3bbafb9a4c11b00000233331944000000003838313031376400cfb4bba4d3c3c6b79f110000028f324a44000000003838313031386400bbafd7b1c6b70000220a00000214de0b44000000003838313031396400bbafcfcb00000000a09a0000020a176f44000000003838313032306400b5d3c2da00000000e0380000029ad96744000000003838313032316400b0b1c2da00000000151500000248498344000000003838313032326400d5b3bdbacfcbceac6e1c000002e17a7444000000003838313032336400bdf5c2da000000006b0d0000027b246a44000000003838313032346400ccbccfcbceac0000ab070000028fa25144000000003838313032356400c6e4cbfbbbafd1a7251b0000021fa5ba44000000003838313032366400bbafd1a7d4adc1cfd6b30100029a498444000000003838313032376400c3babbafb9a400001272000002cd9cc844000000003838313032386400eed1b0d7b7db0000f51a000002b8fe2344000000003838313032396400c2c8bcee000000007f60000002149e2c44000000003838313033306400b4bfbcee00000000843e00000248218444000000003838313033316400cedebbfad1ce00002916000002d7a3b044000000003838313033326400d3d0bbfabbafb9a46b5e00000252086f44000000003838313033336400c6e4cbfbbbafd1a7341300000266169444000000003838313033346400bbafd1a7d6c6c6b72cfc000002a4b06944000000003838313033356400bedbb0b1f5a50000e614000002cd6c8044000000003838313033366400cdbfc1cfd3cdc4abe10d0000025c478844000000003838313033376400c3f1b1acd6c6c6b70a1e000002d7f3a344000000003838313033386400b7c4d6afbbafd1a7b11f000002e18a9744000000003838313033396400b7fabbafb9a4000080180000027185a044000000003838313034306400cab3c6b7d6fabcc1261e000002a4705044000000003838313034316400d3d0bbfab9e80000fd1b000002ecb1ec43000000003838313034326400bdbaf0a4bcc1bcb0390b00000200105344000000003838313034336400c6e4cbfbbbafd1a7ca3d000002d7932c44000000003838313034346400cbdcc1cf00000000aa190100025cb7a344000000003838313034356400bacfb3c9caf7d6ac475c000002ae47d944000000003838313034366400cbdcc1cfb1a1c4a4bb7c00000233639744000000003838313034376400b8c4d0d4cbdcc1cf04140000025caf9d44000000003838313034386400bacfb3c9b8ef0000c608000002a4c8a344000000003838313034396400cbdcc1cfd6fabcc10e1400000233337d44000000003838313035306400c6e4cbfbcbdcc1cfcc0f000002ec51ae44000000003838313035316400cff0bdba00000000f81f0000021f055544000000003838313035326400cff0bdbad6fabcc1fe020000027bf48644000000003838313035336400ccbfbada00000000e608000002aea78c44000000003838313035346400cff0bdbad6c6c6b7131400000252583344000000003838313035356400c5a9d3c3bbafb9a478020100026626a844000000003838313035366400c5a9d2a9000000000c34000002e12a8044000000003838313035376400b5aab7ca00000000c2330000020a476a44000000003838313035386400c1d7b7cabcb0c1d7743200000285bb9644000000003838313035396400bcd8b7ca00000000e711000002ae37f444000000003838313036306400b8b4bacfb7ca00004d56000002d7138044000000003838313036316400b8d6ccfa000000009abf01000214fe7744000000003838313036326400d2b1b8d6d4adc1cf1d180000020038a544000000003838313036336400ccfabff3caaf00005e0f0000023d5adb44000000003838313036346400d2b1b8d6b8a8c1cfbf0800000252c87944000000003838313036356400c6d5b8d6000000000986010002660e8044000000003838313036366400b3a4b2c400000000ed09000002b81e2744000000003838313036376400b0e5b2c40000000002730100020a678144000000003838313036386400c6e4cbfbb8d6b2c41909000002c3859c44000000003838313036396400ccd8b8d600000000722100000248e14944000000003838313037306400d3d0c9ab00000000d1a3030002e1fad244000000003838313037316400b9a4d2b5bdf0caf48fe3010002142a0945000000003838313037326400cdad000000000000d1980000021f9d1145000000003838313037336400c2c100000000000041070100027be40045000000003838313037346400c7a6d0bf000000007d430000028f7af244000000003838313037356400b9f3bdf0caf40000ab5d000002d7e73a45000000003838313037366400bbc6bdf0000000002c42000002854f3645000000003838313037376400b0d7d2f8000000007f1b0000023d365445000000003838313037386400c4dcd4b4bdf0caf420700000023d4a2944000000003838313037396400efae000000000000be4f0000027bb42344000000003838313038316400eedc000000000000281f000002f6a82d44000000003838313038326400cfa1d3d0bdf0caf434c40000020088d844000000003838313038336400cfa1cdc1000000009920000002d7538144000000003838313038346400ced9eee200000000f159000002338f4d45000000003838313038356400eed1000000000000420c000002cd0c8544000000003838313038366400c6e4cbfbbdf0caf4683d0000025c4fc844000000003838313038376400bdf0caf4d0c2b2c4412e000002ecc19744000000003838313038386400b4c5d0d4b2c4c1cf1617000002cd948c44000000003838313038396400c6e4cbfbbdf0caf42a17000002b836b344000000003838313039306400bda8b2c4000000005409010002f6387744000000003838313039316400cbaec4e0000000007935000002ecb14c44000000003838313039326400cbaec4e0d6c6d4ecd725000002ece15044000000003838313039336400cbaec4e0d6c6c6b7a20f000002f6282e44000000003838313039346400b2a3c1a7b2a3cfcbb2880000021456b644000000003838313039356400b2a3c1a7d6c6d4ecf1210000028f825e44000000003838313039366400b2a3cfcbd6c6d4ecc166000002cd8ce744000000003838313039376400d7b0cacebda8b2c4284b000002e1ca4244000000003838313039386400ccd5b4c9000000007906000002ae771e44000000003838313039396400b9dcb2c400000000011500000233a33c44000000003838313130306400c4cdbbf0b2c4c1cfa70800000233d38044000000003838313130316400b7c0cbaeb2c4c1cf6c080000027b840044000000003838313130326400cdbfc1cf00000000d9010000027b544344000000003838313130336400c6e4cbfbbda8b2c4be1c000002855b7a44000000003838313130346400b7c7bdf0caf4b2c4700d000002a4688144000000003838313130356400c5a9c1d6c4c1d3e68892010002e19a5744000000003838313130366400d6d6d6b2d2b50000a659000002cdf48244000000003838313130376400c1b8cab3d6d6d6b27c0b0000020aef9144000000003838313130386400cab3d3c3befa00009c070000025cab5b45000000003838313130396400d6d6d7d300000000e92b00000200e02144000000003838313131306400c6e4cbfbd6d6d6b2a51a000002d7eb9744000000003838313131316400d1f8d6b3d2b500009e4e000002f6185c44000000003838313131326400c9fad6edd1f8d6b3213c000002aed75c44000000003838313131336400c8e2bca6d1f8d6b3f70a000002b8ce5a44000000003838313131346400c6e4cbfbd1f8d6b38507000002859b3d44000000003838313131356400c1d6d2b500000000b43a000002d77f0445000000003838313131366400d3e6d2b500000000031a000002296c6a44000000003838313131376400cbaeb2fad1f8d6b3c3170000029ad95344000000003838313131386400cbaeb2fab2b6c0cc400200000248c1b044000000003838313131396400cbc7c1cf00000000983b000002a4203b44000000003838313132306400d0f3c7ddcbc7c1cf43310000025c5f1e44000000003838313132316400cbaeb2facbc7c1cfc30700000248915c44000000003838313132326400b3e8ceefcab3c6b79102000002cdc48544000000003838313132336400c5a9b2fac6b7bcd33d37000002a4b02844000000003838313132346400c1b8d3cdbcd3b9a4f922000002cd8cff43000000003838313132356400b9fbcadfbcd3b9a4f806000002c315ae44000000003838313132366400c6e4cbfbc5a9b2fa4b0d000002e18a2d44000000003838313132376400b6afceefb1a3bda1b422000002a4705644000000003838313132396400cab3c6b7d2fbc1cf69da00000248212e44000000003838313133306400c4f0bec600000000302f00000266062544000000003838313133316400c6a1bec600000000d912000002cd2c4c44000000003838313133326400c6cfccd1bec600004803000002d7135544000000003838313133336400bbc6bec6000000005104000002b8ee8244000000003838313133346400c6e4cbfbbec6c0e0a801000002c3f5bd43000000003838313133356400b0d7bec60000000014130000020a672344000000003838313133366400d2fbc1cfc8e9c6b70629000002a4406144000000003838313133376400c8edd2fbc1cf0000e40a00000271b5a844000000003838313133386400c8e9d6c6c6b70000211e000002b80e4844000000003838313133396400b5f7ceb6c6b70000e738000002146e1e44000000003838313134306400d0ddcfd0cab3c6b7190f0000020a471c44000000003838313134316400c1e3cab3000000001d0700000266565844000000003838313134326400bae6b1bacab3c6b72505000002b8defe43000000003838313134336400caeccab300000000d6020000027b54ca43000000003838313134346400cab3c6b7bcd3b9a4323a00000266a68644000000003838313134356400c8e2d6c6c6b70000b01c00000285bb774400000000 \ No newline at end of file diff --git a/tests/fixtures/security_list.json b/tests/fixtures/security_list.json new file mode 100644 index 0000000..7bd0181 --- /dev/null +++ b/tests/fixtures/security_list.json @@ -0,0 +1,8 @@ +{ + "num_records": 1000, + "first": { + "code": "999999", + "name": "上证指数", + "pre_close": 11654847.33 + } +} \ No newline at end of file diff --git a/tests/fixtures/security_quotes.hex b/tests/fixtures/security_quotes.hex new file mode 100644 index 0000000..c9315fc --- /dev/null +++ b/tests/fixtures/security_quotes.hex @@ -0,0 +1 @@ +01050100013630303030303e109d0f04040643acfaa60edd0f9889349483013a6ec94da7831cb2851841a6e2020001bd0788124102a8cd0187314203906aab114304a7b4018f1f4405ab96019812560f0000000000003e10 \ No newline at end of file diff --git a/tests/fixtures/security_quotes.json b/tests/fixtures/security_quotes.json new file mode 100644 index 0000000..bc801a9 --- /dev/null +++ b/tests/fixtures/security_quotes.json @@ -0,0 +1,9 @@ +{ + "num_records": 1, + "first": { + "code": "600000", + "pre_close": 9.93, + "unknown_2": -1, + "unknown_3": 22694 + } +} \ No newline at end of file diff --git a/tests/fixtures/transaction.hex b/tests/fixtures/transaction.hex new file mode 100644 index 0000000..b6f929d --- /dev/null +++ b/tests/fixtures/transaction.hex @@ -0,0 +1 @@ +0a0083039e0f0000080083030000000800830300000008008303000000080083030000000800830300000008008303410000080083030000000800830300000008008403009483019f040200 \ No newline at end of file diff --git a/tests/fixtures/transaction.json b/tests/fixtures/transaction.json new file mode 100644 index 0000000..c90a1de --- /dev/null +++ b/tests/fixtures/transaction.json @@ -0,0 +1,9 @@ +{ + "num_records": 10, + "first": { + "hour": 14, + "minute": 59, + "price": 9.9, + "vol": 0 + } +} \ No newline at end of file diff --git a/tests/fixtures/xdxr_info.hex b/tests/fixtures/xdxr_info.hex new file mode 100644 index 0000000..10a35d8 --- /dev/null +++ b/tests/fixtures/xdxr_info.hex @@ -0,0 +1 @@ +01000136303030303057000136303030303000460a31010500000000000000000000fa46005a6b480136303030303000702d3101050000fa46005a6b4800401c47005a6b480136303030303000c22f3101010000c03f0000000000000000000000000136303030303000567e31010100000040000000000000a040000000000136303030303000567e31010200401c47005a6b4800606a478083b048013630303030300097a231010600000000333307410060ea46000000000136303030303000a8a231010800606a478083b04800c8af478029bf4801363030303030009fa43101010000803f000000000000000000000000013630303030300048cb310101cdcc8c3f000000000000000000000000013630303030300050f23101019a99993f00000000000000000000000001363030303030006019320101000000000000000000004040000000000136303030303000601932010500c8af478029bf480084e4478029bf4801363030303030006d193201016666a63f0000000000000000000000000136303030303000ca1b3201080084e4478029bf48951a024809a4d44801363030303030007240320105951a024809a4d4489a359f4809a4d44801363030303030003e413201010000c03f0000000000000000000000000136303030303000da423201059a359f4809a4d448d8c3ac4809a4d44801363030303030002867320101cdcccc3f00000000000040400000000001363030303030002967320105d8c3ac4809a4d4483398e0486c370a49013630303030300080673201053398e0486c370a492ebcf4486c370a490136303030303000908e3201032ebcf4486c370a496c370a496c370a490136303030303000f18e320101333313400000000000008040000000000136303030303000f28e3201026c370a496c370a49ca804149ca80414901363030303030003090320105ca804149ca804149ca804149c9935749013630303030300002b63201010000c03f000000000000404000000000013630303030300003b6320102ca804149c9935749d48d7b490f208c49013630303030300041b7320105d48d7b490f208c490f208c490f208c49013630303030300096b73201050f208c490f208c490f208c491328af4901363030303030000bdd320101cdcccc3f00000000000040400000000001363030303030000fdd3201020f208c491328af49ae29b64919b4e349013630303030300032043301010000404000000000000000000000000001363030303030002b2b3301010000b040000000000000000000000000013630303030300050523301013333d34000000000000000000000000001363030303030005f79330101713df2400000000000000000000000000136303030303000e67a330105ae29b64919b4e34919b4e34919b4e34901363030303030003e9f33010519b4e34919b4e34919b4e34991e7ef4901363030303030006fa0330101cdcca440000000000000803f00000000013630303030300070a033010919b4e34991e7ef494f79fa4990f2034a013630303030300050c63301054f79fa4990f2034a90f2034a90f2034a01363030303030001dc73301010000004000000000000040400000000001363030303030001ec733010990f2034a90f2034a22882b4a22882b4a013630303030300098c833010522882b4a22882b4a22882b4aa026334a0136303030303000e9ee3301010000803f00000000000000000000000001363030303030009315340101000060400000000000000000000000000136303030303000b63c34010522882b4aa026334a2e882b4aad26334a01363030303030000c3d3401052e882b4aad26334a32882b4ab126334a0136303030303000133d3401010000c0400000000000000000000000000136303030303000c83d34010532882b4ab126334ab526334ab526334a0136303030303000e23d340105b526334ab526334ab626334ab626334a01363030303030000f3f340105b626334ab626334ab826334ab826334a01363030303030009b62340105b826334ab826334aba26334aba26334a0136303030303000c663340105ba26334aba26334abe26334abe26334a01363030303030001964340105be26334abe26334ac026334ac026334a013630303030300021643401019a9999400000000000000000000000000136303030303000f264340105c026334ac026334ac226334ac226334a01363030303030001f66340105c226334ac226334ac326334ac326334a0136303030303000ab89340105c326334ac326334ac526334ac526334a0136303030303000d68a340105c526334ac526334ac526334ac526334a0136303030303000288b340105c526334ac526334ac526334ac526334a0136303030303000318b340101333383400000000000000000000000000136303030303000028c340105c526334ac526334ac526334ac526334a01363030303030002f8d340105c526334ac526334ac626334ac626334a0136303030303000bbb0340105c626334ac626334ac626334ac626334a0136303030303000e6b1340105c626334ac626334ac626334ac626334a013630303030300039b2340105c626334ac626334ac626334ac626334a013630303030300041b2340101cdcc4c40000000000000000000000000013630303030300012b3340105c626334ac626334ac726334ac726334a01363030303030003fb4340105c726334ac726334ac726334ac726334a0136303030303000cbd7340105c726334ac726334ac726334ac726334a0136303030303000f6d8340105c726334ac726334ac726334ac726334a01363030303030004ed9340101a4704d40000000000000000000000000013630303030300022da340105c726334ac726334ac726334ac726334a01363030303030004fdb340105c726334ac726334ac726334ac726334a0136303030303000dbfe340105c726334ac726334ac826334ac826334a01363030303030000300350105c826334ac826334a47b8384a47b8384a0136303030303000060035010547b8384a47b8384a48b8384a48b8384a0136303030303000550035010548b8384a48b8384a40bd384a40bd384a01363030303030005c00350101333383400000000000000000000000000136303030303000320135010540bd384a40bd384ab35f3f4ab35f3f4a01363030303030008201350105b35f3f4ab35f3f4a2e853f4a2e853f4a013630303030300085013501052e853f4a2e853f4a9144424a9144424a013630303030300087013501059144424a9144424a3fa1454a3fa1454a013630303030300088013501053fa1454a3fa1454a5162464a5162464a013630303030300089013501055162464a5162464ad88a474ad88a474a01363030303030008f01350105d88a474ad88a474abb8e4a4abb8e4a4a01363030303030009001350105bb8e4a4abb8e4a4a44484b4a44484b4a0136303030303000930135010544484b4a44484b4a5f484b4a5f484b4a \ No newline at end of file diff --git a/tests/fixtures/xdxr_info.json b/tests/fixtures/xdxr_info.json new file mode 100644 index 0000000..f5bfa9d --- /dev/null +++ b/tests/fixtures/xdxr_info.json @@ -0,0 +1,9 @@ +{ + "num_records": 87, + "first": { + "year": 1999, + "month": 11, + "day": 10, + "category": 5 + } +} \ No newline at end of file diff --git a/tests/unit/test_commands_offline.py b/tests/unit/test_commands_offline.py new file mode 100644 index 0000000..bfe4aa6 --- /dev/null +++ b/tests/unit/test_commands_offline.py @@ -0,0 +1,328 @@ +"""离线 fixture 测试:将录制的原始 body 字节喂给各命令 parse_response,验证解析结果。 + +fixtures/ 目录下每个 .hex 文件是一次真实服务器响应的 body(已解压), +对应的 .json 文件记录关键预期值,供手工核对。 +此测试文件直接断言解析结果,无需网络连接。 +""" +from __future__ import annotations + +import pathlib +import pytest + +FIXTURES = pathlib.Path(__file__).parent.parent / "fixtures" + + +def load_hex(name: str) -> bytes: + return bytes.fromhex((FIXTURES / f"{name}.hex").read_text().strip()) + + +# --------------------------------------------------------------------------- +# security_count +# --------------------------------------------------------------------------- + +def test_security_count_parse(): + from xmtdx.commands.security_count import GetSecurityCountCmd + from xmtdx.models.enums import Market + + body = load_hex("security_count") + cmd = GetSecurityCountCmd(Market.SH) + count = cmd.parse_response(body) + + assert isinstance(count, int) + assert count > 0 + # 体积固定为 2 字节,结果与录制时完全一致 + assert count == 26885 + + +# --------------------------------------------------------------------------- +# security_list +# --------------------------------------------------------------------------- + +def test_security_list_parse(): + from xmtdx.commands.security_list import GetSecurityListCmd + from xmtdx.models.enums import Market + + body = load_hex("security_list") + cmd = GetSecurityListCmd(Market.SH, 0) + records = cmd.parse_response(body) + + assert len(records) == 1000 + + r0 = records[0] + assert r0.code == "999999" + assert r0.name == "上证指数" + # pre_close is a float; the index level is stored ×100 and has many decimal places + assert abs(r0.pre_close - 11654847.33) < 1.0 + + # _raw present and non-empty for every record + assert all(len(r._raw) > 0 for r in records) + + +def test_security_list_gbk_no_crash(): + """Bug #2 修复验证:GBK 解码不崩溃,所有记录均有 code。""" + from xmtdx.commands.security_list import GetSecurityListCmd + from xmtdx.models.enums import Market + + body = load_hex("security_list") + cmd = GetSecurityListCmd(Market.SH, 0) + records = cmd.parse_response(body) + assert all(r.code for r in records) + + +# --------------------------------------------------------------------------- +# security_bars +# --------------------------------------------------------------------------- + +def test_security_bars_parse(): + from xmtdx.commands.security_bars import GetSecurityBarsCmd + from xmtdx.models.enums import Market, KlineCategory + + body = load_hex("security_bars") + cmd = GetSecurityBarsCmd(Market.SH, "600000", KlineCategory.DAY, 0, 5) + bars = cmd.parse_response(body) + + assert len(bars) == 5 + + b0 = bars[0] + assert abs(b0.open - 10.25) < 0.01 + assert abs(b0.high - 10.25) < 0.01 + assert abs(b0.low - 10.08) < 0.01 + assert abs(b0.close - 10.12) < 0.01 + assert b0.vol > 0 + + # OHLC sanity: high ≥ open,close,low; low ≤ open,close + for bar in bars: + assert bar.high >= bar.open - 0.001 + assert bar.high >= bar.close - 0.001 + assert bar.low <= bar.open + 0.001 + assert bar.low <= bar.close + 0.001 + assert bar.vol > 0 + assert len(bar._raw) > 0 + + +# --------------------------------------------------------------------------- +# security_quotes +# --------------------------------------------------------------------------- + +def test_security_quotes_parse(): + from xmtdx.commands.security_quotes import GetSecurityQuotesCmd + from xmtdx.models.enums import Market + + body = load_hex("security_quotes") + cmd = GetSecurityQuotesCmd([(Market.SH, "600000")]) + quotes = cmd.parse_response(body) + + assert len(quotes) == 1 + + q = quotes[0] + assert q.code == "600000" + assert abs(q.pre_close - 9.93) < 0.01 + + # unknown fields are captured (not discarded) + assert hasattr(q, "unknown_2") + assert hasattr(q, "unknown_3") + assert hasattr(q, "unknown_5") + assert hasattr(q, "unknown_6") + assert hasattr(q, "unknown_7") + assert hasattr(q, "unknown_8") + assert hasattr(q, "rise_speed") + assert len(q._raw) > 0 + + # fixed values from frozen fixture + assert q.unknown_2 == -1 + assert q.unknown_3 == 22694 + + +# --------------------------------------------------------------------------- +# minute_time +# --------------------------------------------------------------------------- + +def test_minute_time_parse(): + from xmtdx.commands.minute_time import GetMinuteTimeDataCmd + from xmtdx.models.enums import Market + + body = load_hex("minute_time") + cmd = GetMinuteTimeDataCmd(Market.SH, "600000") + bars = cmd.parse_response(body) + + assert len(bars) == 240 + + b0 = bars[0] + assert isinstance(b0.price, float) + assert isinstance(b0.vol, int) + # Bug #5 fix: unknown_1 is preserved, not discarded + assert hasattr(b0, "unknown_1") + assert isinstance(b0.unknown_1, int) + assert len(b0._raw) > 0 + + # fixed values + assert abs(b0.price - 0.01) < 0.001 + assert b0.vol == 48 + assert b0.unknown_1 == 54 + + +# --------------------------------------------------------------------------- +# history_minute_time +# --------------------------------------------------------------------------- + +def test_history_minute_time_parse(): + from xmtdx.commands.minute_time import GetHistoryMinuteTimeDataCmd + from xmtdx.models.enums import Market + + body = load_hex("history_minute_time") + cmd = GetHistoryMinuteTimeDataCmd(Market.SH, "600000", 20250108) + bars = cmd.parse_response(body) + + assert len(bars) == 240 + + b0 = bars[0] + assert abs(b0.price - 10.29) < 0.01 + assert b0.vol == 10044 + assert hasattr(b0, "unknown_1") + assert len(b0._raw) > 0 + + +# --------------------------------------------------------------------------- +# transaction (current day) +# --------------------------------------------------------------------------- + +def test_transaction_parse(): + from xmtdx.commands.transaction import GetTransactionDataCmd + from xmtdx.models.enums import Market + + body = load_hex("transaction") + cmd = GetTransactionDataCmd(Market.SH, "600000", 0, 10) + recs = cmd.parse_response(body) + + assert len(recs) == 10 + + r0 = recs[0] + assert r0.hour == 14 + assert r0.minute == 59 + assert abs(r0.price - 9.9) < 0.01 + assert r0.vol == 0 + + # Bug #4 fix: unknown_last captured + assert hasattr(r0, "unknown_last") + assert len(r0._raw) > 0 + + # buyorsell: 0=buy, 1=sell, 2=neutral, 8=auction — field is an int + for r in recs: + assert isinstance(r.buyorsell, int) + + +# --------------------------------------------------------------------------- +# history_transaction +# --------------------------------------------------------------------------- + +def test_history_transaction_parse(): + from xmtdx.commands.transaction import GetHistoryTransactionDataCmd + from xmtdx.models.enums import Market + + body = load_hex("history_transaction") + cmd = GetHistoryTransactionDataCmd(Market.SH, "600000", 20250108, 0, 10) + recs = cmd.parse_response(body) + + assert len(recs) == 10 + + r0 = recs[0] + assert r0.hour == 14 + assert r0.minute == 56 + assert abs(r0.price - 10.3) < 0.01 + assert r0.vol == 50 + + assert hasattr(r0, "unknown_last") + assert len(r0._raw) > 0 + + for r in recs: + assert isinstance(r.buyorsell, int) + + +# --------------------------------------------------------------------------- +# xdxr_info +# --------------------------------------------------------------------------- + +def test_xdxr_info_parse(): + from xmtdx.commands.xdxr_info import GetXdxrInfoCmd + from xmtdx.models.enums import Market + + body = load_hex("xdxr_info") + cmd = GetXdxrInfoCmd(Market.SH, "600000") + recs = cmd.parse_response(body) + + assert len(recs) == 87 + + r0 = recs[0] + assert r0.year == 1999 + assert r0.month == 11 + assert r0.day == 10 + assert r0.category == 5 + + # Bug #1 fix: each record has a unique date (not all reading from body[:7]) + dates = {(r.year, r.month, r.day) for r in recs} + assert len(dates) > 1, "All records have the same date — Bug #1 not fixed!" + + assert all(len(r._raw) > 0 for r in recs) + + +# --------------------------------------------------------------------------- +# finance_info +# --------------------------------------------------------------------------- + +def test_finance_info_parse(): + from xmtdx.commands.finance_info import GetFinanceInfoCmd + from xmtdx.models.enums import Market + + body = load_hex("finance_info") + cmd = GetFinanceInfoCmd(Market.SH, "600000") + info = cmd.parse_response(body) + + # Check key fields are present and reasonable + assert info.liutong_guben > 0 + assert info.zong_guben > 0 + assert info.meigujing_zichan > 0 + + # Fixed values from frozen fixture + assert abs(info.liutong_guben - 33305837500.0) < 1e6 + assert abs(info.zong_guben - 33305837500.0) < 1e6 + assert abs(info.meigujing_zichan - 22.13) < 0.1 + + assert len(info._raw) > 0 + + +# --------------------------------------------------------------------------- +# company_info_category +# --------------------------------------------------------------------------- + +def test_company_info_category_parse(): + from xmtdx.commands.company_info import GetCompanyInfoCategoryCmd + from xmtdx.models.enums import Market + + body = load_hex("company_info_category") + cmd = GetCompanyInfoCategoryCmd(Market.SH, "600000") + cats = cmd.parse_response(body) + + assert len(cats) == 16 + + c0 = cats[0] + assert c0.filename == "600000.txt" + assert c0.start == 0 + assert c0.length == 11426 + + +# --------------------------------------------------------------------------- +# company_info_content +# --------------------------------------------------------------------------- + +def test_company_info_content_parse(): + from xmtdx.commands.company_info import GetCompanyInfoContentCmd + from xmtdx.models.enums import Market + + body = load_hex("company_info_content") + cmd = GetCompanyInfoContentCmd(Market.SH, "600000", "600000.txt", 0, 11426) + text = cmd.parse_response(body) + + assert isinstance(text, str) + assert len(text) == 8070 + assert "600000" in text + assert "浦发银行" in text