Files
sfgrid/SFGrid_Flowchart.md
T
2026-06-12 16:25:41 +08:00

8.5 KiB
Raw Blame History

SFGrid 网格交易策略流程图

1. 总览:策略生命周期

flowchart TD
    A["SFGridStrategy.__init__()"] --> B["订阅事件总线<br/>onOrderCreateAsync / onOrderTrade / onOrderError"]
    B --> C["获取涨跌停价<br/>todayUpStopPrice / todayDownStopPrice"]
    C --> D["loadExistOrders()<br/>从券商侧恢复未成交订单到 orderGrid"]
    D --> E["enabledTrading(enabled)"]
    E --> F{"enabled ?"}
    F -->|True| G["启用交易流程 → 见 §3"]
    F -->|False| H["停用交易流程 → 见 §3"]
    G --> I["saveProxy() 持久化"]
    H --> I
    I --> J["构造完成,进入事件循环<br/>等待 QMT 回调 / UI 操作"]

2. 核心:refreshGridOrder() 网格下单

flowchart TD
    START["refreshGridOrder()"] --> CHECK1{"qmtv.isMarketActive<br/>AND<br/>tradeTarget.enabled ?"}
    CHECK1 -->|No| SKIP["跳过不下单"]
    CHECK1 -->|Yes| QUERY["查询未成交订单<br/>queryPendingOrder()"]

    QUERY --> STATUS{"tradeTarget.status ?"}

    STATUS -->|"= 0 未建仓"| CHECK_INIT{"已存在建仓单?<br/>remark = 'INIT,1,{code}'"}
    CHECK_INIT -->|"No 没有"| PLACE_INIT["下建仓单 (STOCK_BUY)<br/>价格 = getPriceGrid()[0]<br/>remark = 'INIT,1,{code}'"]
    CHECK_INIT -->|"Yes 已有"| DONE_INIT["建仓单已在途,跳过"]

    STATUS -->|"= 1 已建仓"| GET_IDX["currentIdx = grid_index"]
    GET_IDX --> SELL_CHECK{"currentIdx > 0 ?<br/>(grid_index 不是最低点)"}
    SELL_CHECK -->|"Yes 可挂卖单"| SELL_EXIST{"已存在同 remark 卖单?<br/>remark='SELL,{idx-1},{code}'"}
    SELL_EXIST -->|"No 没有"| SELL_PLACE["下卖出单 (STOCK_SELL)<br/>价格 = grid[sellIdx]<br/>sellIdx = currentIdx - 1"]
    SELL_EXIST -->|"Yes 已有"| SELL_SKIP["跳过,避免重复"]
    SELL_CHECK -->|"No 价格已最低"| SELL_SKIP2["无卖出空间"]

    SELL_PLACE --> BUY_CHECK
    SELL_SKIP --> BUY_CHECK
    SELL_SKIP2 --> BUY_CHECK

    BUY_CHECK{"currentIdx < len(grid)-1 ?<br/>(grid_index 不是最高点)"}
    BUY_CHECK -->|"Yes 可挂买单"| BUY_EXIST{"已存在同价同类型买单?<br/>order_type=BUY AND price=buyPrice"}
    BUY_EXIST -->|"No 没有"| BUY_PLACE["下买入单 (STOCK_BUY)<br/>价格 = grid[buyIdx]<br/>buyIdx = currentIdx + 1"]
    BUY_EXIST -->|"Yes 已有"| BUY_SKIP["跳过,避免重复"]
    BUY_CHECK -->|"No 价格已最高"| BUY_SKIP2["无买入空间"]

3. 交易启停:enabledTrading()

flowchart TD
    START["enabledTrading(enabled)"] --> SET["self.tradeTarget.enabled = enabled"]
    SET --> BRANCH{"enabled ?"}

    BRANCH -->|"True 启用"| STATUS{"tradeTarget.status ?"}
    STATUS -->|"= 0 未建仓"| INIT_IDX{"grid_index == 0 ?"}
    INIT_IDX -->|"Yes"| SET1["grid_index = 1<br/>(默认建仓位置)"]
    INIT_IDX -->|"No"| KEEP["保留现有 grid_index"]
    SET1 --> REFRESH1["refreshGridOrder()"]
    KEEP --> REFRESH1

    STATUS -->|"= 1 已建仓"| CALC["计算最小需求仓位<br/>min = grid_volume × grid_index"]
    CALC --> CHECK{"current_position >= min ?"}
    CHECK -->|"Yes 充足"| REFRESH2["refreshGridOrder()"]
    CHECK -->|"No 不足"| DENY["拒绝启用<br/>enabled = False<br/>(风控保护)"]

    BRANCH -->|"False 停用"| CANCEL["取消所有未成交订单<br/>cancel_order_stock_async()"]
    CANCEL --> LOG["记录取消数量"]

    REFRESH1 --> SAVE["saveProxy() 持久化"]
    REFRESH2 --> SAVE
    DENY --> SAVE
    LOG --> SAVE

4. 事件回调链

flowchart TD
    subgraph QMT["QMT / xtquant 层"]
        OA["orderAsync()<br/>返回 seq"]
        PUSH_ERR["C扩展推送<br/>XtOrderError"]
        PUSH_RESP["C扩展推送<br/>XtOrderResponse"]
        PUSH_TRADE["C扩展推送<br/>XtTrade"]
    end

    subgraph BUS["事件总线 event_bus"]
        EVT_ERR["MarketOrderError"]
        EVT_RESP["MarketOrderCreated"]
        EVT_TRADE["MarketOrderTraded"]
    end

    subgraph STG["SFGridStrategy 回调"]
        OE["onOrderError()"]
        OC["onOrderCreateAsync()"]
        OT["onOrderTrade()"]
    end

    OA --> PUSH_RESP
    OA --> PUSH_ERR
    PUSH_ERR --> EVT_ERR --> OE
    PUSH_RESP --> EVT_RESP --> OC
    PUSH_TRADE --> EVT_TRADE --> OT

5. onOrderError() 委托失败处理

flowchart TD
    START["onOrderError(order_error)"] --> CHK1{"order_remark 非空 ?"}
    CHK1 -->|"No 空"| EXIT1["无法解析,忽略"]
    CHK1 -->|"Yes"| PARSE["解析 remark<br/>'{type},{gridIdx},{stockCode}'"]
    PARSE --> CHK2{"len(parts) >= 3 ?"}
    CHK2 -->|"No"| EXIT1
    CHK2 -->|"Yes"| CHK3{"strategy_name == 'SFGRID'<br/>AND<br/>stockCode 匹配本标的 ?"}
    CHK3 -->|"No 不匹配"| EXIT1
    CHK3 -->|"Yes"| LOCK["获取 dataUpdateLock"]
    LOCK --> DEL{"gridIdx in orderGrid ?"}
    DEL -->|"Yes"| REMOVE["del orderGrid[gridIdx]<br/>清理孤立条目"]
    DEL -->|"No"| LOG_ERR["记录错误日志<br/>error_id / error_msg"]
    REMOVE --> LOG_ERR
    LOG_ERR --> UNLOCK["释放 dataUpdateLock"]

6. onOrderCreateAsync() 订单确认

flowchart TD
    START["onOrderCreateAsync(response)"] --> PARSE["解析 remark<br/>'{type},{gridIdx},{stockCode}'"]
    PARSE --> FILTER{"strategy_name == 'SFGRID'<br/>AND len(parts) >= 3<br/>AND stockCode 匹配 ?"}
    FILTER -->|"No"| EXIT["忽略"]
    FILTER -->|"Yes"| LOCK["获取 dataUpdateLock"]
    LOCK --> UPDATE["orderGrid[gridIdx] = response.order_id<br/>seq → order_id 替换"]
    UPDATE --> UNLOCK["释放 dataUpdateLock"]

7. onOrderTrade() 成交处理

flowchart TD
    START["onOrderTrade(trade)"] --> PARSE["解析 remark<br/>'{type},{gridIdx},{stockCode}'"]
    PARSE --> FILTER{"strategy_name == 'SFGRID'<br/>AND len(parts) >= 3<br/>AND stockCode 匹配 ?"}
    FILTER -->|"No"| EXIT["忽略"]
    FILTER -->|"Yes"| LOCK["获取 dataUpdateLock"]

    LOCK --> TYPE{"orderType ?"}

    TYPE -->|"INIT 建仓单"| INIT["status = 1<br/>init_price = traded_price<br/>grid_index = 1"]
    TYPE -->|"BUY / SELL 网格单"| CMP{"gridIdx vs grid_index ?"}

    CMP -->|"gridIdx > grid_index<br/>(买入成交)"| DOWN["grid_index += 1<br/>下移一格"]
    CMP -->|"gridIdx < grid_index<br/>(卖出成交)"| UP["grid_index -= 1<br/>上移一格<br/>match_count += 1<br/>total_profit += grid_size × volume"]
    CMP -->|"gridIdx == grid_index<br/>(异常)"| SAME["日志: 理论上不应该输出"]

    INIT --> POST
    DOWN --> POST
    UP --> POST
    SAME --> POST

    POST["成交后处理"] --> SAVE["saveProxy() 持久化状态"]
    SAVE --> DEL["del orderGrid[gridIdx]<br/>移除已成交订单"]
    DEL --> REPORT["打印成交报告<br/>成交价/量/手续费"]
    REPORT --> REFRESH["refreshGridOrder()<br/>在新位置挂新的网格单"]
    REFRESH --> UNLOCK["释放 dataUpdateLock"]

8. 网格交易完整状态机

stateDiagram-v2
    [*] --> 未建仓: 创建 SFGridStrategy
    未建仓 --> 建仓中: enabledTrading(True)<br/>下建仓单 INIT

    建仓中 --> 已建仓: onOrderTrade(INIT)<br/>建仓单成交
    建仓中 --> 建仓失败: onOrderError(INIT)<br/>委托被拒

    建仓失败 --> 建仓中: refreshGridOrder()<br/>重新下建仓单

    已建仓 --> 网格运行: refreshGridOrder()<br/>上下各挂一单

    网格运行 --> 网格运行: onOrderTrade(SELL)<br/>卖出成交 → 上移<br/>重新挂单
    网格运行 --> 网格运行: onOrderTrade(BUY)<br/>买入成交 → 下移<br/>重新挂单
    网格运行 --> 单边挂单: onOrderError<br/>某方向委托失败

    单边挂单 --> 网格运行: refreshGridOrder()<br/>重新补挂失败方向的单

    已建仓 --> 已停用: enabledTrading(False)<br/>取消所有挂单
    网格运行 --> 已停用: enabledTrading(False)
    单边挂单 --> 已停用: enabledTrading(False)

    已停用 --> 已建仓: enabledTrading(True)<br/>仓位检查通过
    已停用 --> 已停用: enabledTrading(True)<br/>仓位不足,回退

9. 网格价格示意

价格
 ↑
 │  grid[5] = 12.00  ← 最贵(顶部)
 │  grid[4] = 11.50
 │  grid[3] = 11.00  ← 当前位置 grid_index=3
 │  grid[2] = 10.50      上方挂卖单 @10.50 (sellIdx=2, grid_index-1)
 │  grid[1] = 10.00      下方挂买单 @10.00 (buyIdx=1, 已成交位置)
 │  grid[0] =  9.50  ← 最便宜(底部/建仓价)
 │
 └──────────────────────→

  grid_index=3 时:
    卖单挂在 grid[2] @10.50 → 价格跌到 10.50 卖出(上移一格,赚差价)
    买单挂在 grid[4] @11.50 → 价格涨到 11.50 买入(下移一格,补仓)

  grid_size = grid[i] - grid[i-1] = 0.50(每格利润空间)