How 800 Lines Added Binance Futures Trading to ITB Using Codex and GLM‑5.2 (Full Testnet Verification)

The article details how the author extended the intelligent‑trading‑bot (ITB) with a new Binance futures execution pipeline using Codex CLI for TDD and GLM‑5.2 for context hand‑off, illustrating three business chains, incremental computation, state‑machine design, crash recovery, risk controls, and nine real‑world bugs uncovered during full testnet verification.

Hacker Afternoon Tea
Hacker Afternoon Tea
Hacker Afternoon Tea
How 800 Lines Added Binance Futures Trading to ITB Using Codex and GLM‑5.2 (Full Testnet Verification)

Three Business Pipelines

ITB consists of three independent pipelines that together form a signal‑to‑order trading system.

Pipeline 1 (offline) : downloads historical Binance K‑lines, computes features and labels, writes intermediate CSV files, and trains two classifiers that predict a 2 % upward move (high_20_lc) and a 2 % downward move (low_20_lc). The final train step consumes matrix.csv (features + labels) and produces two .pickle model files containing weights and scalers.

Pipeline 2 (online) : runs every minute via APScheduler, fetches the newest K‑lines, and performs incremental feature computation only on the newly added rows. A dirty_records tracker marks rows that need recomputation, keeping per‑tick latency to a few hundred milliseconds. The loaded models generate probability columns high_20_lc and low_20_lc. A combine generator subtracts the two to obtain trade_score. The threshold_rule marks rows with trade_score > +0.015 as buy signals and rows with trade_score < ‑0.015 as sell signals, adding boolean columns buy_signal_column and sell_signal_column to the dataframe.

Pipeline 3 (futures trade execution) : consumes the signal‑enriched dataframe, reads the current position from the exchange via futures_position_information, performs risk checks, and opens or closes Binance futures positions.

Pipeline 1 – Offline Training Sequence

The offline script is a six‑step serial pipeline. Each step reads the CSV output of the previous step and writes a new CSV. The final train step reads matrix.csv, trains two classifiers (one for upward moves, one for downward moves), and writes two .pickle files that contain the model weights and the associated scalers. These files are later loaded by the online server.

Pipeline 2 – Online Incremental Prediction

Every minute the server wakes, fetches the latest K‑lines, and processes only the new rows. The dirty_records set tracks which rows need recomputation; after processing they are marked clean, keeping the per‑tick computation time to a few hundred milliseconds.

The model predicts two probability columns high_20_lc and low_20_lc. The combine generator computes trade_score = high_20_lc - low_20_lc. The threshold_rule creates a buy signal when trade_score > +0.015 and a sell signal when trade_score < ‑0.015, storing the results in buy_signal_column and sell_signal_column. At this point the dataframe’s last row contains the two boolean signal columns; the original ITB system stops here, producing signals only.

Pipeline 3 – Futures Trade Execution (added layer)

The new trader_futures module reads the dataframe with signals, queries the exchange for the true position (no local position state), and applies a three‑state finite‑state machine (FLAT → LONG → SHORT). FLAT opens a position on the first signal, LONG closes on a sell signal, SHORT closes on a buy signal; same‑direction signals are ignored. This design is simpler than the spot version’s four‑state FSM because futures support native shorting.

After opening a position the system immediately places a STOP_MARKET order with closePosition=true. If the server crashes after the tick, the stop‑loss remains on the exchange and will automatically liquidate the position when the price reaches the stop level.

When a signal flips (e.g., from SELL to BUY) the system sends a closing order with reduceOnly=true to prevent accidental reverse trades, writes the realized P&L to daily_pnl.json, and the risk‑control circuit breaker reads this file on restart.

Full‑Chain Testnet Run

Analyze finished. Close: 60,293 Signals: trade_score=-0.218, sell_signal_column=True
Opened SELL position: {'orderId': 16531286193, 'status': 'NEW', 'origQty': '0.0330'}
Placed STOP_MARKET stop at 60896.09

The testnet log shows a SELL signal that opened a short position of 0.033 BTC at 60271.6 USDT, placed a STOP_MARKET at 60896.09 USDT, and reported an unrealized P&L of +0.38 USDT.

Closing Logic

When the signal column flips from SELL to BUY, the system automatically closes the position, uses reduceOnly=true to avoid reverse trades, and records the realized P&L in daily_pnl.json. The risk‑control module reads this file after a restart, ensuring consistent behavior.

Crash Recovery

If the server restarts with an orphaned position (open but without a stop‑loss), the recovery routine automatically re‑places the missing STOP_MARKET order. The initial implementation attempted to detect existing stop orders with futures_get_open_orders, but algo orders are hidden from that endpoint, causing error ‑4130. The fix is to skip the query, call cancel_all, and then re‑place the stop order, making the process idempotent.

Four‑Layer Risk Controls

Risk is enforced through four independent safeguards. Reverse signals are always allowed to pass so that stop‑loss exits cannot be blocked by the circuit‑breaker. The mandatory STOP_MARKET order guarantees that a position can be liquidated even if the server crashes.

Nine Real‑World Pitfalls Discovered

Pitfall: STOP_MARKET cannot be cancelled. Root cause: Algo order uses a different endpoint. Fix: Use cancel_all_open_orders.

Pitfall: Open error ‑4130. Root cause: Residual stop order conflict. Fix: Call cancel_all before placing a new order.

Pitfall: Open error ‑4005. Root cause: Size interpreted as USDT instead of BTC. Fix: Divide the desired BTC amount by the entry price.

Pitfall: Recovery error ‑4130. Root cause: futures_get_open_orders hides algo orders. Fix: Skip the query, execute cancel_all, then re‑place the stop order.

Pitfall: collector_binance undefined. Root cause: Missing import. Fix: Add the appropriate import statement.

Pitfall: get_last_kline argument error. Root cause: Method does not accept parameters. Fix: Remove the extraneous parameters.

Pitfall: Series truth ambiguity. Root cause: Incorrect index selection. Fix: Use kline["close"] to obtain the close price.

Pitfall: Numba SIGILL. Root cause: JIT compilation crashes inside Docker. Fix: Set environment variable NUMBA_DISABLE_JIT=1.

Pitfall: API keys committed to Git. Root cause: .jsonc file not ignored. Fix: Add the file pattern to .gitignore.

E2E ≠ Full Chain

All‑green end‑to‑end (E2E) tests validate only the internal logic of pipeline 3 with mock signals; they do not verify the hand‑off from pipeline 2 to pipeline 3. Running the full server exposed three bugs in the integration layer that the E2E suite missed, demonstrating the necessity of complete end‑to‑end validation.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

risk managementincremental computationCodex CLIAI tradingGLM-5.2Binance futures
Hacker Afternoon Tea
Written by

Hacker Afternoon Tea

You might find something interesting here ^_^

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.