Skip to content

Latest commit

 

History

History
943 lines (669 loc) · 36.4 KB

File metadata and controls

943 lines (669 loc) · 36.4 KB

Poly Maker 代码导览与扩展手册

这份文档把你当成刚接触这个仓库的人来写。目标不是让你马上记住每一行代码,而是让你知道:

  • 程序从哪里启动。
  • 每个目录负责什么。
  • 每个文件、类、函数大概做什么。
  • 想加某个功能时应该改哪里。
  • 后续做方向预测、机器学习、实时优化时,从哪里开始最稳。

1. 一句话理解这个项目

这是一个 Polymarket 做市机器人。它会定期读取目标市场 YES/NO 两个 token 的盘口、持仓、最近成交和奖励信息,然后用一个短期预测器估计 fair price,再生成 GTC + Post-only 挂单,最后通过 Polymarket CLOB API 下单、撤单和同步订单。

核心主路径是:

main.py
  -> BotConfig 读取 .env
  -> PolymarketAdapter 连接 Polymarket
  -> MarketMaker.bootstrap 解析市场和初始化 predictor
  -> MarketMaker.tick 循环执行策略
  -> AdvancedPredictor 预测短期价格
  -> QuoteEngine 生成 maker-safe limit price
  -> OrderReconciler 决定保留/撤销/新挂哪些订单
  -> PolymarketAdapter 下单、撤单、查持仓
  -> DataRecorder 记录每轮数据

2. 主 Pipeline

2.1 启动阶段

flowchart TD
    A["uv run python main.py"] --> B["BotConfig: 读取 .env"]
    B --> C["config.validate: 校验关键参数"]
    C --> D["setup_logging: 控制台和日志文件"]
    D --> E["PolymarketAdapter: 初始化 CLOB client"]
    E --> F{"MARKET_SOURCE"}
    F -->|"env"| G["MarketMaker(config, adapter).run()"]
    F -->|"google_sheet"| H["load_google_sheet_markets"]
    H --> I["为多个市场创建 MarketMaker"]
Loading

2.2 每一轮 tick 的策略流程

flowchart TD
    A["MarketMaker.tick"] --> B["获取 YES/NO order book"]
    B --> C["计算 bid/ask/mid 和 orderbook imbalance"]
    C --> D["读取持仓和全局 exposure"]
    D --> E["读取 recent trades -> trade_flow"]
    E --> F["AdvancedPredictor 生成 predicted_mid"]
    F --> G["风险检查: exposure/stop-loss/take-profit/jump/close-only"]
    G --> H["QuoteEngine 生成 BUY/SELL limit price"]
    H --> I["TargetOrder 列表"]
    I --> J["OrderReconciler 比较 live open orders"]
    J --> K["cancel stale orders"]
    K --> L["place missing orders"]
    F --> M["DataRecorder 写 CSV"]
Loading

2.3 你现在日志里的每行对应哪里

  • [MARKET] YES: Mid=... 来自 MarketMaker.tick,记录当前盘口。
  • [PREDICT] YES: PredMid=... 来自 MarketMaker.tick 调用 AdvancedPredictor.predict 后。
  • [QUOTE] BUY YES fair=... 来自 QuoteEngine.log_diagnostics
  • YES buy quote ... 来自 MarketMaker._build_buy_order
  • [RECONCILE] live keep=... 来自 MarketMaker._sync_target_ordersOrderReconciler.plan
  • [TRADE] Placing BUY YES... 来自 MarketMaker._place_orders
  • [API_SUCCESS] Posted BUY YES... 来自 PolymarketAdapter.place_limit_order

3. 目录总览

.
├── main.py                         # 主入口
├── config.py                       # .env 配置读取与校验
├── market_maker.py                 # 做市策略主循环
├── polymarket_adapter.py           # Polymarket API 适配层
├── quote_engine.py                 # 报价引擎
├── emergency_exit.py               # 紧急 maker 退出逻辑
├── order_reconciler.py             # GTC 订单同步/保留队列位置
├── predictors.py                   # 基础预测接口
├── advanced_predictors.py          # 当前使用的增强预测器
├── data_recorder.py                # 每轮行情/预测/持仓数据记录
├── market_sources.py               # 从 .env 或 Google Sheet 加载市场
├── resolve_market.py               # URL/slug/condition_id 转 token id
├── discover_markets.py             # 发现可交易市场
├── latency_probe.py                # 延迟测量工具
├── check_auth.py                   # 签名类型/钱包配置排查工具
├── tests/                          # 单元测试
├── poly_data/                      # 旧版/辅助数据和交易工具链
├── data_updater/                   # 更新 Google Sheet 市场数据
├── poly_utils/                     # Google Sheet 读取工具
├── poly_stats/                     # 账户统计
└── poly_merger/                    # Node.js 持仓合并工具

你日常跑做市机器人时,最重要的是根目录这些文件:

main.py
config.py
market_maker.py
polymarket_adapter.py
quote_engine.py
emergency_exit.py
order_reconciler.py
advanced_predictors.py
predictors.py
data_recorder.py

poly_data/data_updater/trading.py 更像历史版本或辅助工具,理解主策略时可以先跳过。

4. 核心文件详解

4.1 main.py

用途:程序入口,负责启动配置、日志、API adapter 和 MarketMaker。

函数:

  • setup_logging(log_file):配置日志格式,同时输出到终端和 LOG_FILE
  • main():读取 BotConfig,校验配置,创建 PolymarketAdapter,然后按 MARKET_SOURCE 选择单市场或多市场运行。

你想改:

  • 启动方式、日志格式、多市场调度:改这里。
  • 策略逻辑:不要改这里,去 market_maker.py

4.2 config.py

用途:把 .env 里的字符串变成程序可用的配置对象。

辅助函数:

  • _env(name, default):读取环境变量;空字符串当作没有设置。
  • _env_any(*names, default):按多个名字依次读取,支持新旧变量名兼容。
  • _decimal(name, default):读取 Decimal 类型参数。
  • _int(name, default):读取 int 类型参数。
  • _bool(name, default):读取 bool 类型参数。
  • _decimal_from_env(key, default):直接从 os.environ 读取 Decimal。

类:

  • BotConfig:所有 bot 参数的集中定义。

BotConfig 重要字段:

  • 账户连接:private_keyfunder_addresssignature_typeclob_api_keyclob_secretclob_passphrase
  • 市场选择:condition_idtoken_yestoken_nomarket_source
  • 运行参数:dry_runorder_notional_usdcrefresh_interval_seconds
  • 风控参数:max_market_exposure_usdcmax_token_exposure_usdcstop_loss_pcttake_profit_pct
  • 预测参数:prediction_latency_msprediction_edge_bpsmin_prediction_confidenceorderbook_imbalance_levels
  • 订单行为:order_typepost_onlycancel_on_start

属性/方法:

  • spread_fraction:把 bps 转成比例。
  • inventory_skew_fraction:库存偏斜 bps 转比例。
  • stop_loss_fraction:止损百分比转比例。
  • take_profit_fraction:止盈百分比转比例。
  • max_midpoint_move_fraction:mid 快速跳变阈值转比例。
  • fok_price_buffer_fraction:FOK buffer bps 转比例。
  • fok_min_edge_fraction:FOK 最小 edge bps 转比例。
  • validate():启动前校验参数,发现危险配置就报错或警告。

你想加新 env 参数:

  1. BotConfig 里新增字段。
  2. validate() 里加合理性检查。
  3. 在使用它的模块里通过 self.config.xxx 读取。

4.3 polymarket_adapter.py

用途:把 Polymarket SDK/API 包一层,主策略不直接碰 SDK 细节。

数据类:

  • FatalTradingError:不可重试的交易错误,例如 invalid signature。
  • TokenConfig:一个 outcome token 的交易配置,包括 token_idoutcometick_sizeneg_riskmin_order_sizeend_date_iso
  • Quote:最简盘口,包含 bidaskmid
  • Position:持仓信息,包含 token_idsizeavg_pricecurrent_price
  • Position.notional:当前持仓名义金额,size * current_price
  • Position.unrealized_pnl:未实现盈亏。
  • OrderBookSnapshot:完整盘口快照,包含 quotebidsasks

类:

  • PolymarketAdapter:Polymarket 交互中心。

函数/方法:

  • __init__(config):初始化 CLOB client,设置 key、creds、signature_type、funder,并在缺少 L2 creds 时尝试自动 derive。
  • resolve_tokens():从 .env 的 token id 或 condition id 解析 YES/NO token。
  • resolve_market_spec(spec):从 Google Sheet 的 MarketSpec 解析 token。
  • find_reward_market_condition_id():从 rewards 市场里自动找候选市场。
  • get_quote(token):获取某个 token 的简化 Quote
  • get_order_book_snapshot(token):获取完整 order book,计算 best bid/ask/mid。
  • get_positions(tokens, quotes):读取目标 YES/NO token 的持仓。
  • get_global_exposure():读取账户所有仓位并计算总 exposure。
  • get_all_positions():读取账户全部持仓。
  • cancel_market_orders(condition_id):撤某个 condition_id 下的订单。
  • cancel_token_orders(token_id):撤某个 token 下的订单。
  • cancel_orders(order_ids):按订单 id 批量撤单。
  • open_orders_for_token(token_id):读取某 token 当前 open orders。
  • place_limit_order(token, side, price, size, dry_run):创建并提交限价单;这是实盘下单的核心方法。
  • round_price(value, tick_size, rounding):按 tick size 四舍/向上/向下取整。
  • today_rewards_estimate(condition_id):读取当天 rewards 估计。
  • _token_config(token_id, outcome, end_date_iso):从 SDK 查询 tick size、neg risk、min order size,生成 TokenConfig
  • _extract_tokens_from_market(market):从 market API 返回里提取 token id。
  • _levels(book, name):把 SDK order book 的 bids/asks 转成 (price, size) 列表。
  • _data_api_positions():调用 data-api 读取 funder 地址持仓。
  • get_recent_trades(token_id):读取最近成交,用于 trade flow。

你想改:

  • API 字段兼容、签名、下单、撤单:改这里。
  • 想接 WebSocket 替代 REST 盘口:通常新增 adapter 方法,然后在 MarketMaker.tick 调用。
  • 想支持新钱包类型:优先改 .env;真的需要代码兼容时改 __init__

4.4 market_maker.py

用途:策略主循环。它决定每一轮看什么数据、做什么预测、挂什么单、什么时候停。

类:

  • MarketMaker:一个市场的做市机器人实例。

生命周期方法:

  • __init__(config, adapter, spec, predictor):保存配置、adapter、预测器、报价引擎、订单同步器和状态变量。
  • run():完整运行循环,包含 bootstrap、tick、异常重试、退出撤单。
  • shutdown():设置停止标记并撤单。
  • next_sleep_seconds():返回每轮 sleep 时间。
  • bootstrap():解析市场、初始化 predictor、启动 DataRecorder、启动时撤旧单、记录初始 exposure。

核心策略方法:

  • _calculate_trade_flow(trades):把最近成交转成 -1 到 1 的方向性因子。正值代表买方更激进,负值代表卖方更激进。
  • tick():每一轮策略主函数。读取行情、持仓、recent trades、计算预测、生成订单、记录数据、同步订单。
  • _build_buy_order(...):根据预测价格、风控、持仓限制生成 BUY TargetOrder
  • _build_sell_order(...):根据持仓、止盈止损、close-only 生成 SELL TargetOrder
  • _calculate_limit_price(...):调用 QuoteEngine 得到最终限价。
  • _sync_target_orders(orders, tokens):调用 OrderReconciler,决定保留、撤销、新挂订单。
  • _place_orders(orders):逐个执行目标订单。
  • _execute_order_with_retry(order, max_retries):下单,余额不足时自动降低 notional 重试;post-only crossed 时放弃。

风控方法:

  • _position_return(position):计算某个 token 当前收益率。
  • _position_risk_off(token, quote, position):检查止损/止盈,必要时进入 risk-off。
  • _market_loss_limit_hit(unrealized_pnl):检查整个市场未实现亏损是否超过上限。
  • _midpoint_jump_detected(token, quote):检查 mid 单轮跳变是否过大。
  • _is_close_only_window():临近结束时间时只平仓不开新仓。
  • _shares_for_notional(order_notional, price, token):把美元 notional 转成 shares,并处理最小下单量。
  • _current_market_exposure():计算当前目标市场 exposure。
  • _cancel_working_orders():撤当前市场或当前两个 token 的挂单。

特征计算方法:

  • _calculate_orderbook_imbalance(bids, asks):计算前 N 档 bid/ask 深度不平衡。
  • _top_of_book_sizes(bids, asks):取 best bid size 和 best ask size。

系统方法:

  • _install_signal_handlers():处理 Ctrl+C / SIGTERM,优雅退出。
  • _cancel_reconciled_orders(plan):执行订单同步计划里的撤单部分。

你想改:

  • 增加新的实时特征:先在 tick() 里计算。
  • 增加新的风控规则:放在 _build_buy_order 前或 _position_risk_off 附近。
  • 改下单节奏:改 tick()next_sleep_seconds()
  • 改何时买/卖:改 _build_buy_order / _build_sell_order
  • 接入新预测器:构造函数传 predictor,或改 bootstrap() 默认 predictor。

4.5 predictors.py

用途:定义预测器接口和基础 OBI 预测器。

数据类:

  • MarketFeatures:基础特征,包含 token、quote、imbalance、latency_ms、best bid/ask size。
  • Prediction:预测结果,包含 predicted_midedge_bpsconfidencereason

类:

  • ShortHorizonPredictor:预测器抽象接口。
  • ShortHorizonPredictor.predict(features):子类必须实现。
  • ImbalancePredictor:基础 OBI + microprice 预测器。
  • ImbalancePredictor.__init__(impact_bps_per_imbalance, min_confidence):设置 OBI 权重和最低置信度。
  • ImbalancePredictor.predict(features):输出预测 mid。
  • ImbalancePredictor._microprice_edge_bps(features):根据 best bid/ask size 计算 microprice 相对 mid 的 edge。

你想改:

  • 新增模型接口字段:改 MarketFeatures
  • 新增预测器:新建类继承 ShortHorizonPredictor
  • 模型输出不仅是价格,还要输出风险:扩展 Prediction

4.6 advanced_predictors.py

用途:当前主策略实际使用的增强预测器。

数据类:

  • AdvancedMarketFeatures:继承 MarketFeatures,增加 trade_flowvolatility

类:

  • AdvancedPredictor:使用 microprice、orderbook imbalance、trade flow、短窗口波动率的预测器。

方法:

  • __init__(impact_bps_per_imbalance, min_confidence, volatility_window):设置 OBI 权重、最低置信度、波动率窗口。
  • predict(features):计算 volatility、base edge、trade flow adjustment、confidence,输出 Prediction
  • _microprice_edge_bps(features):和基础预测器类似,计算 microprice edge。

当前局限:

  • latency_ms 只写进 reason,没有真正改变特征窗口。
  • trade_flow_adjustment_bps = trade_flow * 10 是硬编码。
  • volatility 是每个 predictor 一个 deque,如果一个 predictor 同时服务 YES/NO,两个 token 的 mid history 会混在一起。

你想做方向预测:

  • 第一版先改这里,把硬编码权重变成多因子线性模型。
  • 更成熟后新建 research_predictors.pyml_predictor.py

4.7 quote_engine.py

用途:把预测 fair value 变成实际可挂的 maker-safe limit price。

数据类:

  • TargetOrder:策略想要挂的订单,包含 token、side、price、shares、reason。
  • TargetOrder.notional:订单名义金额。
  • QuoteDiagnostics:报价诊断数据,用于日志。

类:

  • QuoteEngine:报价引擎。

方法:

  • __init__(config, adapter):保存配置和 adapter。
  • calculate_limit_price(token, side, predicted_mid, quote, position, market_conviction_yes):核心报价函数。
  • log_diagnostics(diagnostics):输出 [QUOTE] 日志。
  • _inventory_skew(quote, position):库存越多,买价越保守。
  • _directional_skew(token, quote, market_conviction_yes):根据 YES 市场 conviction 调整 YES/NO 报价。
  • _gtc_post_only_price(token, side, adjusted_fair, quote):GTC Post-only 模式下,确保 BUY 不高于 ask - tick,SELL 不低于 bid + tick
  • _experimental_fok_price(side, predicted_mid, quote):实验 FOK 模式报价。

你想改:

  • MIN_EXPECTED_EDGE_BPS:这里最合适。
  • 想调整报价更激进/保守:改 _gtc_post_only_pricecalculate_limit_price
  • 想做库存管理:改 _inventory_skew

4.8 emergency_exit.py

用途:模块化处理“已有 YES/NO 持仓突然逆向时,尽快用 maker 挂单退出”的逻辑。

数据类:

  • EmergencyExitSignal:紧急退出判断结果,包含是否触发、触发原因、持仓收益率、midpoint 变动、逆向盘口不平衡。

类:

  • EmergencyExitEngine:紧急退出引擎。

方法:

  • __init__(config):保存紧急退出相关配置。
  • evaluate(token, quote, position, previous_mid, imbalance):判断某个 token 的持仓是否触发紧急退出。YES 和 NO 对称处理。
  • build_maker_exit_order(token, quote, position, signal):触发后生成 SELL @ best_bid + tick 的 aggressive maker 退出单。

你想改:

  • 想更早/更晚触发应急:调 EMERGENCY_EXIT_LOSS_PCTEMERGENCY_EXIT_MIDPOINT_MOVE_BPSEMERGENCY_EXIT_IMBALANCE_THRESHOLD
  • 想拆单退出:调 EMERGENCY_EXIT_MAX_SHARES
  • 想升级到 taker escape:未来在这个模块里新增 taker escalation 状态,不要塞回 MarketMaker.tick()

4.9 order_reconciler.py

用途:GTC 挂单不要每轮无脑撤换。它会比较目标订单和 live open orders,尽量保留不变的订单队列位置。

数据类:

  • ReconciliationPlan:订单同步计划。
  • ReconciliationPlan.has_work:是否需要撤单/挂单。

类:

  • OrderReconciler:订单同步器。

方法:

  • __init__(adapter):保存 adapter。
  • plan(desired_orders, last_targets, tokens, condition_id, use_live_orders):主函数,输出 keep/place/cancel 计划。
  • _plan_from_last_targets(desired_orders, last_targets):dry-run 或 live open orders 读取失败时,用上轮目标做 fallback。
  • _load_open_orders(tokens):读取 YES/NO 两个 token 的 open orders。
  • _same_targets(new_orders, old_orders):判断目标价格和数量是否几乎没变。
  • _target_key(order):用 (token_id, side) 标记目标订单。
  • _open_order_key(row):从 live open order 里提取 (token_id, side)
  • _open_order_id(row):提取订单 id。
  • _open_order_price(row):提取订单价格。
  • _open_order_size(row):提取订单剩余数量。
  • _find_matching_open_order(desired, rows):找和目标价格/数量匹配的 live order。

你想改:

  • 想减少撤单:提高 _same_targets 的容忍度。
  • 想每隔 N 秒强制刷新队列:在 plan() 增加时间逻辑。
  • 想支持多档挂单:这里和 TargetOrder 的 key 逻辑要一起改。

4.10 data_recorder.py

用途:异步写 CSV,记录每轮行情、预测和持仓数据。

类:

  • DataRecorder

方法:

  • __init__(condition_id):创建 logs/market_data_...csv,启动后台写线程。
  • _write_loop():从队列取数据并追加到 CSV。
  • record(data):把一行数据放进队列。
  • stop():停止写线程并等待队列刷完。

你想做研究:

  • 第一优先改 MarketMaker.tick() 里的 tick_data_to_log 字段。
  • 想写 parquet/duckdb:改这里。
  • 想做实时 dashboard:可以在这里同时推到 SQLite 或 WebSocket。

4.11 market_sources.py

用途:支持从 Google Sheet 读取多个市场。

数据类:

  • MarketSpec:一个市场的 condition id、YES token、NO token、问题文本、结束时间。

函数:

  • load_google_sheet_markets(config):读取指定 worksheet,转成 MarketSpec 列表。
  • _worksheet_df(spreadsheet, title):读取 sheet 并转 DataFrame。
  • _merge_selected_with_all(spreadsheet, selected):Selected Markets 只有 question 时,和 All Markets 合并补全 token。
  • _first(row, names):从一行里按多个可能列名取第一个非空值。
  • _df_to_specs(df):DataFrame 转 MarketSpec

你想改:

  • 新增市场来源,比如数据库或 JSON:可以新增 load_xxx_markets
  • Google Sheet 列名变化:改 _df_to_specs

5. 工具脚本

5.1 resolve_market.py

用途:从 Polymarket 网页 URL、slug、event slug、condition id 解析 .env 所需字段。

函数:

  • path_parts(value):拆 URL path。
  • normalize_slug(value):把 URL 或 slug 归一成 market slug。
  • normalize_event_slug(value):把 URL 或 slug 归一成 event slug。
  • get_json(url):GET JSON,404 返回空 dict。
  • parse_jsonish(value):兼容 list、JSON 字符串、普通字符串。
  • market_from_slug(slug, index, contains):从 market slug 或 event slug 找具体 market。
  • event_markets_from_slug(slug, contains):列出 event 下的 markets。
  • print_event_markets(markets, prefix):打印 event 下的子市场列表。
  • market_from_condition_id(condition_id):用 CLOB client 按 condition id 查 market。
  • extract_market(value, index, contains):自动判断输入是 condition id 还是 slug。
  • list_markets(value, contains):列出 event 下所有子市场。
  • print_env(market):打印 QUESTIONCONDITION_IDTOKEN_ID_YESTOKEN_ID_NO
  • main():命令行入口。

5.2 discover_markets.py

用途:发现 markets,尤其是 rewards/sports 市场。

函数:

  • _text(item):从 market/reward item 中拼接可搜索文本。
  • _condition_id(item):提取 condition id。
  • _tokens_from_market(market):提取 token ids。
  • print_market(client, condition_id, title):打印市场详情。
  • main():命令行入口。

5.3 latency_probe.py

用途:测量 quote fetch、预测/签名、本地处理、post ack 延迟。

函数:

  • _ms(start, end):纳秒转毫秒。
  • _p95(values):计算 p95。
  • _safe_probe_price(adapter, token, snapshot):生成不会跨盘口的测试价格。
  • main():命令行入口;默认 dry-run 安全测量,--post-probe 会真实提交小订单。

5.4 check_auth.py

用途:排查 invalid signature,打印 signer、funder、signature type,但不打印私钥。

函数:

  • mask(value):地址脱敏。
  • main():读取 BotConfig 并打印认证信息。

5.5 update_markets.py

用途:定时更新 Google Sheet 里的市场列表、奖励和波动率数据。

函数:

  • update_sheet(data, worksheet):把 DataFrame 写回 worksheet。
  • sort_df(df):按奖励、波动率、价格区间计算排序分数。
  • fetch_and_process_data():拉市场、算指标、写 All Markets / Volatility Markets / Full Markets。

5.6 update_stats.py

用途:每 3 小时更新账户统计。

没有自定义函数,主逻辑在 if __name__ == '__main__' 里循环调用 poly_stats.account_stats.update_stats_once

5.7 trading.py

用途:旧版做市逻辑,依赖 poly_data.global_state。主策略已经转移到 market_maker.py,一般不建议在这里扩展新功能。

函数:

  • send_buy_order(order):旧版 BUY 下单逻辑,会按价格/数量变化决定是否撤旧单。
  • send_sell_order(order):旧版 SELL 下单逻辑。
  • perform_trade(market):旧版异步交易主函数,包含 position merge、盘口分析、买卖逻辑。

6. poly_data/ 目录

这是旧版或辅助工具链,很多逻辑依赖全局变量和 Google Sheet。新策略主路径不强依赖它。

6.1 poly_data/polymarket_client.py

用途:旧版 Polymarket client 包装。

类:

  • PolymarketClient

方法:

  • __init__(pk):初始化 SDK client、凭证、钱包信息。
  • create_order(marketId, action, price, size, neg_risk):创建并提交订单。
  • get_order_book(market):获取 order book。
  • get_usdc_balance():获取 USDC 余额。
  • get_pos_balance():获取仓位价值。
  • get_total_balance():获取总资产估计。
  • get_all_positions():读取全部持仓。
  • get_raw_position(tokenId):读取链上原始 token 仓位。
  • get_position(tokenId):读取格式化仓位。
  • get_all_orders():读取全部 open orders。
  • get_market_orders(market):读取某市场订单。
  • cancel_all_asset(asset_id):撤某 token 订单。
  • cancel_all_market(marketId):撤某市场订单。
  • merge_positions(amount_to_merge, condition_id, is_neg_risk_market):调用合并持仓工具。

6.2 poly_data/data_processing.py

用途:处理 websocket/book/user 数据并更新全局状态。

函数:

  • process_book_data(asset, json_data):处理某 token 的 order book。
  • process_price_change(asset, side, price_level, new_size, asset_id):处理盘口某档变化。
  • process_data(json_datas, trade):处理市场 websocket 数据。
  • add_to_performing(col, id):把某市场/任务标记为执行中。
  • remove_from_performing(col, id):移除执行中标记。
  • process_user_data(rows):处理用户 websocket 数据,例如订单和持仓。

6.3 poly_data/data_utils.py

用途:维护旧版全局 positions/orders/markets。

函数:

  • update_positions(avgOnly):刷新持仓。
  • get_position(token):读取某 token 本地持仓。
  • set_position(token, side, size, price, source):更新本地持仓。
  • update_orders():刷新订单。
  • get_order(token):读取某 token 本地订单。
  • set_order(token, side, size, price):更新本地订单。
  • update_markets():刷新市场状态。

6.4 poly_data/trading_utils.py

用途:旧版做市报价工具函数。

函数:

  • get_best_bid_ask_deets(market, name, size, deviation_threshold):获取盘口关键档位。
  • find_best_price_with_size(price_dict, min_size, reverse):找满足最小数量的价格档。
  • get_order_prices(...):根据盘口、持仓、参数计算买卖价格。
  • round_down(number, decimals):向下取整。
  • round_up(number, decimals):向上取整。
  • get_buy_sell_amount(position, bid_price, row, other_token_position):计算买卖数量。

6.5 poly_data/websocket_handlers.py

用途:旧版 websocket 连接。

函数:

  • connect_market_websocket(chunk):连接市场 websocket。
  • connect_user_websocket():连接用户 websocket。

6.6 其他文件

  • poly_data/CONSTANTS.py:旧版常量。
  • poly_data/abis.py:链上合约 ABI。
  • poly_data/global_state.py:旧版全局状态容器。
  • poly_data/utils.py
    • pretty_print(txt, dic):打印字典。
    • get_sheet_df(read_only):读取 Google Sheet 数据。
  • poly_data/__init__.py:包标记文件。

7. data_updater/ 目录

用于维护 Google Sheet 市场池,不是主下单循环。

7.1 data_updater/find_markets.py

函数:

  • get_sel_df(spreadsheet, sheet_name):读取 selected markets。
  • get_all_markets(client):获取所有市场。
  • get_bid_ask_range(ret, TICK_SIZE):根据盘口和 tick size 生成价格范围。
  • generate_numbers(start, end, TICK_SIZE):生成 tick 对齐价格列表。
  • add_formula_params(curr_df, midpoint, v, daily_reward):添加奖励公式相关参数。
  • process_single_row(row, client):处理单个市场行。
  • get_all_results(all_df, client, max_workers):并发处理所有市场。
  • get_combined_markets(new_df, new_markets, sel_df):合并新市场和已选市场。
  • calculate_annualized_volatility(df, hours):计算年化波动率。
  • add_volatility(row):给单个市场添加波动率。
  • add_volatility_to_df(df, max_workers):并发添加波动率。
  • get_markets(all_results, sel_df, maker_reward):筛选出适合做市的市场。

7.2 data_updater/google_utils.py

函数/类:

  • get_spreadsheet(read_only):返回 Google Sheet 对象。
  • ReadOnlySpreadsheet.__init__(spreadsheet_url):保存 sheet id。
  • ReadOnlySpreadsheet._extract_sheet_id(url):从 URL 提取 sheet id。
  • ReadOnlySpreadsheet.worksheet(title):返回只读 worksheet。
  • ReadOnlyWorksheet.__init__(sheet_id, title):保存 sheet id 和 tab 名。
  • ReadOnlyWorksheet.get_all_records():读取全部记录。
  • ReadOnlyWorksheet.get_all_values():读取全部单元格值。

7.3 data_updater/trading_utils.py

函数:

  • get_clob_client():创建 CLOB client。
  • approveContracts():执行合约授权。
  • market_action(marketId, action, price, size):对某市场下单。
  • get_position(marketId):读取某市场持仓。

8. poly_utils/poly_stats/

8.1 poly_utils/google_utils.py

data_updater/google_utils.py 类似,是 Google Sheet 读取工具。

函数/类:

  • get_spreadsheet(read_only):获取 Google Sheet。
  • ReadOnlySpreadsheet.__init__(spreadsheet_url):保存 spreadsheet id。
  • ReadOnlySpreadsheet._extract_sheet_id(url):解析 Google Sheet URL。
  • ReadOnlySpreadsheet.worksheet(title):获取 worksheet。
  • ReadOnlyWorksheet.__init__(sheet_id, title):初始化只读 worksheet。
  • ReadOnlyWorksheet.get_all_records():读取记录。
  • ReadOnlyWorksheet.get_all_values():读取原始值。

8.2 poly_stats/account_stats.py

用途:账户统计和报表。

函数:

  • get_markets_df(wk_full):读取市场表。
  • get_all_orders(client):读取全部订单。
  • get_all_positions(client):读取全部持仓。
  • combine_dfs(orders_df, positions, markets_df, selected_df):合并订单、持仓、市场信息。
  • get_earnings(client):读取收益。
  • update_stats_once(client):执行一次账户统计更新。

9. poly_merger/ 目录

用途:Node.js 工具,用于合并 YES/NO 持仓释放抵押品。

9.1 poly_merger/merge.js

函数:

  • mergePositions(amountToMerge, conditionId, isNegRiskMarket):根据是否 neg-risk 选择不同合约调用,然后通过 Safe 执行合并交易。

9.2 poly_merger/safe-helpers.js

函数:

  • joinHexData(hexData):拼接 hex 数据。
  • abiEncodePacked(...params):模拟 Solidity abi.encodePacked
  • signTransactionHash(signer, message):签 Safe 交易 hash。
  • signAndExecuteSafeTransaction(signer, safe, to, data, overrides):签名并执行 Safe 交易。

9.3 poly_merger/safeAbi.js

用途:Safe 合约 ABI。

10. tests/ 目录

tests/test_strategy_components.py

用途:主策略核心组件的单元测试。

辅助函数/类:

  • token(token_id, outcome):生成测试用 TokenConfig
  • config(**overrides):生成测试用配置对象。
  • FakeAdapter:测试用 adapter。
  • FakeAdapter.round_price(...):测试价格取整。
  • FakeAdapter.open_orders_for_token(token_id):测试 open orders。
  • reload_config(monkeypatch, **env):测试环境变量读取。
  • adapter_config(**overrides):测试 adapter 初始化配置。

测试函数:

  • test_config_reads_current_clob_credential_env_names:测试新 CLOB credential env 名。
  • test_config_reads_legacy_clob_credential_env_names:测试旧 CLOB credential env 名。
  • test_adapter_prefers_explicit_creds_over_auto_derive:显式 credentials 优先于自动 derive。
  • test_adapter_auto_derives_creds_in_dry_run:dry-run 也会 derive L2 creds。
  • test_recent_trades_returns_empty_when_l2_auth_missing:L2 auth 缺失时 recent trades 返回空。
  • test_quote_engine_keeps_gtc_buy_below_ask:GTC buy 不跨 ask。
  • test_reconciler_keeps_unchanged_dry_run_targets:目标不变时保留订单。
  • test_reconciler_refreshes_when_price_moves_one_tick:价格变一 tick 时刷新。
  • test_reconciler_uses_live_open_orders_to_cancel_stale_and_place_missing:live orders 下撤 stale、补 missing。
  • test_advanced_predictor_uses_trade_flow_and_latency_reason:预测器使用 trade flow 并记录 horizon。
  • test_adapter_posts_gtc_post_only_order:adapter 传递 GTC/Post-only 参数。
  • test_market_maker_does_not_mark_post_only_reject_as_placed:post-only 拒单不算成功挂单。

11. 想加功能时改哪里

11.1 想加一个新的实时特征

例子:加入 spread_bpsyes_no_summid_return_3tick

改动位置:

  1. market_maker.pytick():计算特征。
  2. advanced_predictors.pyAdvancedMarketFeatures:增加字段。
  3. advanced_predictors.pypredict():使用新字段。
  4. DataRecorder 的记录行:把新字段写入 CSV。
  5. tests/test_strategy_components.py:加测试。

11.2 想换方向预测模型

最稳路径:

  1. 新建 ml_predictors.py
  2. 定义新类继承 ShortHorizonPredictor
  3. 输入仍然使用 AdvancedMarketFeatures 或新 feature dataclass。
  4. 输出仍然是 Prediction
  5. MarketMaker.bootstrap() 里替换默认 predictor。

不要一开始直接改 MarketMaker.tick() 的下单逻辑。先保持接口不变,只换 predictor。

11.3 想做离线训练

推荐新增:

research/
  label_market_data.py
  train_linear_predictor.py
  backtest_predictor.py

数据来自:

logs/market_data_<condition_id>_<timestamp>.csv

第一版标签:

future_mid_100ms
future_mid_500ms
future_return_bps_100ms
future_return_bps_500ms

第一版模型:

future_return_bps =
  w1 * microprice_edge_bps
+ w2 * imbalance
+ w3 * trade_flow
+ w4 * mid_return_3tick
+ w5 * yes_no_deviation

11.4 想减少 adverse selection

改动位置:

  • quote_engine.py:增加 expected edge 检查。
  • market_maker.py:在 _build_buy_order / _build_sell_order 里决定是否跳过订单。
  • config.py:新增 MIN_EXPECTED_EDGE_BPSADVERSE_SELECTION_BUFFER_BPS

核心思想:

只有 predicted_mid 相对 limit_price 有足够优势时才挂单。

11.5 想加多档挂单

改动位置:

  • quote_engine.py:生成多个 TargetOrder
  • market_maker.py_build_buy_order / _build_sell_order 返回 list 或新增 builder。
  • order_reconciler.py_target_key 不能只用 (token_id, side),需要加 level,例如 (token_id, side, level)
  • tests/test_strategy_components.py:补 reconciliation 测试。

11.6 想接 WebSocket

改动位置:

  • 新增 market_data_feed.py 或扩展 polymarket_adapter.py
  • MarketMaker.tick() 从 feed cache 取 order book,而不是每轮 REST。
  • poly_data/websocket_handlers.py 可参考,但不要直接搬旧全局状态模式。

11.7 想做自动调参

改动位置:

  • market_maker.py:维护最近 N 次预测/成交表现。
  • config.py:加开关,例如 ENABLE_ADAPTIVE_EDGE=true
  • advanced_predictors.py:暴露权重可更新。

第一版规则:

  • 最近预测命中率低:降低 prediction_edge_bps
  • post-only reject 多:报价退后一 tick。
  • 成交后短时间亏损多:提高最小 edge 门槛。
  • spread 变宽/volatility 上升:降低 order size。

12. 后续研究方向

12.1 短期方向预测

目标:预测未来 100ms、500ms、2s 的 mid return。

推荐特征:

  • spread_bps
  • microprice_edge_bps
  • imbalance_1
  • imbalance_3
  • imbalance_5
  • bid_depth_1
  • ask_depth_1
  • trade_flow_1s
  • trade_flow_5s
  • mid_return_1tick
  • mid_return_3tick
  • mid_volatility_10tick
  • yes_mid + no_mid - 1

推荐模型顺序:

  1. 手写多因子线性模型。
  2. 离线 Linear/Ridge/Logistic Regression。
  3. LightGBM/XGBoost。
  4. Online SGD。
  5. 深度学习。这个最后再做。

12.2 做市质量优化

关注指标:

  • fill rate:挂单成交率。
  • adverse fill rate:成交后短时间价格反向的比例。
  • post-only reject rate:post-only 被拒比例。
  • queue survival time:订单保留在队列里的时间。
  • realized spread:成交后若干秒的实际 spread 收益。
  • inventory skew:库存偏离程度。

12.3 风控研究

可以加入:

  • 市场波动率动态 order size。
  • 单边库存动态报价退让。
  • YES/NO sum 偏离时暂停报价。
  • 新闻/赛况事件前自动 close-only。
  • 短时间成交过密时降频。

13. 新手阅读顺序

推荐按这个顺序读:

  1. README.md:知道怎么跑。
  2. ENV_CONFIG_GUIDE.md:知道 env 参数。
  3. 本文档第 1-4 节:知道主 pipeline。
  4. main.py:看启动。
  5. market_maker.py:看 tick。
  6. quote_engine.py:看报价。
  7. advanced_predictors.py:看预测。
  8. polymarket_adapter.py:看 API。
  9. order_reconciler.py:看订单同步。
  10. tests/test_strategy_components.py:看关键行为如何被测试。

14. 最小修改原则

以后加功能时,尽量遵守:

  • 预测逻辑放 predictor。
  • 报价逻辑放 quote engine。
  • API 细节放 adapter。
  • 策略流程放 market maker。
  • 配置只放 config。
  • 数据记录放 data recorder。
  • 测试补在 tests。

这样代码会越来越模块化,不会变成所有逻辑都塞进 tick() 的大泥球。