The theory
Short-horizon price movement is often better studied as the result of order-book events and aggressive trade flow than as a sequence of candles.
From microstructure evidence to a guarded exchange SDK workflow
A crypto order-flow system reconstructs a live limit order book, measures how depth and aggressive trades change through time, and tests whether that pressure is large enough to beat spread, fees, slippage, latency, and risk buffers.
This article does not provide entries, exits, position sizing, leverage settings, or production parameters. It describes a software workflow for research, replay, and paper evaluation before any exchange-facing use is considered.
Technical research boundary
This is engineering research for software developers and professional review. It is not aimed at UK retail consumers, and it is not financial advice, a financial promotion, a trade signal, or an instruction to trade any cryptoasset.
Treat the examples as hypothetical software design. Live order placement stays out of scope unless a separate reviewed project approves scope, credentials, exchange rules, risk limits, and operator controls.
Short-horizon price movement is often better studied as the result of order-book events and aggressive trade flow than as a sequence of candles.
Order-flow findings are venue-specific and regime-specific; they should be treated as hypotheses to test on the exact symbols, product type, fee tier, and latency profile used by the system.
Start with public data capture and deterministic replay. The worked example later uses Binance market data and order endpoints, but the workflow is designed to transfer to other crypto venues and products.
Execution gate
paper first, demo next, live only by explicit flag
Theory
Order flow is a testable microstructure hypothesis. The aim is not to infer intent from a chart; it is to measure whether the arriving event stream is adding demand, removing supply, confirming through aggressive trades, and doing so strongly enough to pay execution costs.
The useful signal is a sequence: aggressive flow changes the book, refill confirms or rejects the pressure, and the later markout proves whether the pressure cleared costs.
Resting book
Displayed depth exists on both sides of the mid.
Aggressive flow arrives
Buyer-initiated trades lift offers near the touch.
Refill test
Weak ask refill keeps near-touch supply thin.
Markout window
The system measures whether executable price moves enough after costs.
A limit order book changes when traders submit limit orders, cancel resting orders, or send marketable orders. The system needs the direction and size of those changes: whether demand is being added, supply is being removed, and whether aggressive traders are lifting offers or hitting bids.
The working hypothesis is that synchronized buyer-initiated trades, positive order-flow imbalance near the touch, rising microprice, and weak ask refill can precede very short-horizon upward moves. The inverse pattern can be a reason to sell existing inventory or stay flat in a long-flat spot implementation, while derivatives or margin products need separate short-exposure logic.
Displayed bid and ask size can be cancelled or replenished. That is why the system measures event-driven OFI, trade-flow imbalance, refill, and depletion instead of treating a single depth snapshot as a trading signal.
Multi-level order-flow imbalance treats changes across several book levels as a vector rather than reducing the book to only the best bid and ask. This matters when near-touch pressure is different from pressure two to five basis points away.
Order-flow features can describe pressure, but an exchange order still has to clear spread, maker or taker fees, symbol filters, slippage, queue risk, latency, rejected orders, stale data, and product-specific position rules. The strategy should reject many otherwise plausible trades.
For liquid crypto pairs such as BTCUSDT, an order-flow system may have a measurable short-horizon edge when short-window trade-flow imbalance, event OFI, multi-level pressure, microprice edge, and ask depletion agree, provided the expected move is large enough after all execution costs and risk buffers. In spot-only accounts this naturally becomes long-flat; where futures or margin are available, short exposure must be modeled as a separate execution surface.
Direction
Predict future mid-price or executable markout at 250 ms, 500 ms, 1 s, 3 s, 5 s, and 10 s horizons.
Execution
Evaluate entry markout after spread, modeled fees, queue assumptions, adverse selection, and cancel/submit latency.
Robustness
Walk forward by day and regime, compare public live capture against replay, and require stable results across no-trade thresholds.
Safety
Block the system on sequence gaps, stale streams, disconnected private state, abnormal spread, reject bursts, or daily loss gates.
Evidence
The studies do not prove that any live crypto strategy will make money. They support a narrower engineering hypothesis: order-flow features are worth testing, and they should be tested as event-time, cost-aware signals rather than chart patterns.
| Hypothesis | Takeaway | Sources |
|---|---|---|
| Order-flow imbalance at the best bid and ask is a useful short-horizon explanatory variable for price changes. | Implement event OFI from bid/ask transitions and test it against future executable markouts, not just last-price candles. | |
| Order-flow-derived stationary features can outperform models trained directly on raw order-book states. | Start with normalized, stationary features and simple baselines before adding deep sequence models. | |
| Order-flow changes deeper in the book can add information beyond the top level. | Compute multi-level and basis-point-band features instead of only top-of-book imbalance. | |
| In a cryptocurrency market study, trade-flow imbalance was reported as especially useful for explaining contemporaneous price changes. | Classify public trades by direction so the system can tell whether buyer-initiated or seller-initiated volume is actually arriving. | |
| Bitcoin order imbalance has been studied as an input to crash-risk nowcasting, but crypto evidence remains regime-dependent. | Treat imbalance as a risk and regime signal too, not only as an entry signal. | |
| The Binance worked example exposes the streams and REST snapshots needed to reconstruct a local order book and consume public trade data. | Use diff depth with a REST snapshot, trade or aggregate trade streams, and bookTicker; do not build the strategy from candles only. |
Data
A working order-flow system needs both a correct market-data pipeline and the exchange metadata that makes orders valid. Binance spot endpoints and SDK functions are used here as the concrete example, but the same categories apply to other crypto venues and product types.
The strategy should not score signals until the local book has been anchored, aligned, and marked healthy. Many implementation errors show up here before the model matters.
Open streams
Depth and trade events start arriving before the snapshot is requested.
Buffer deltas
Keep update IDs and receive timestamps while the snapshot is in flight.
Fetch snapshot
Use the REST book as the anchor for the local book state.
Align IDs
Drop covered events and apply only the remaining ordered deltas.
Mark healthy
Rebuild on gaps, stale streams, checksum failures, or crossed states.
| Input | Surface | Fields | Why it matters | Sources |
|---|---|---|---|---|
| Diff depth stream | symbol@depth or symbol@depth@100ms | U, u, b, a, event time | Primary source for book changes. Use the official snapshot-plus-buffer procedure to build a local book and rebuild on gaps. | |
| REST order-book snapshot | GET /api/v3/depth via MainClient.getOrderBook() | lastUpdateId, bids, asks, limit up to 5000 | Anchors the local book before applying buffered diff-depth events. | |
| Trade or aggregate trade stream | symbol@trade or symbol@aggTrade | price, quantity, trade time, buyer-maker flag | Signs aggressive flow. In the Binance spot example, buyer-maker true means the buyer was the maker, so the taker side is sell. | |
| Book ticker | symbol@bookTicker or GET /api/v3/ticker/bookTicker | best bid, best bid quantity, best ask, best ask quantity | Low-latency cross-check for the top of book, spread, and stale local-book detection. | |
| Exchange and symbol filters | GET /api/v3/exchangeInfo via MainClient.getExchangeInfo() | PRICE_FILTER, LOT_SIZE, MIN_NOTIONAL or NOTIONAL, MARKET_LOT_SIZE | Prevents invalid prices, quantities, and notionals before orders are submitted. | |
| Private order state | User data stream plus REST reconciliation | executionReport, balances, open orders, fills | Confirms whether submitted orders were accepted, filled, partially filled, canceled, or rejected. |
Findings
For implementation, keep the system focused on four checks: reconstruct the event stream, confirm pressure with trades, subtract realistic costs, and block exchange writes until replay, paper trading, and risk gates pass.
A depth snapshot is useful context, but it is not a signal by itself. Track additions, cancellations, and consumption around the touch so the model sees pressure changing over time.
Public trades classified by direction show whether aggressive buyers or sellers are actually crossing the spread. Displayed liquidity without matching trade flow is weaker evidence.
Pressure at the best bid or ask can disagree with depth a few ticks away. Keep level bands and basis-point distance bands so the model does not overreact to the top of book alone.
A signal that looks strong before costs may disappear after maker or taker fees, spread, queue risk, slippage, symbol filters, and latency are included.
Test normalized features, rolling z-scores, logistic or ridge regression, and gradient-boosted trees before adding a deep sequence model.
Even a correct direction can lose if the book is stale, the spread is abnormal, sequence state is broken, or private exchange state is not reconciled.
Market surface
The same order-flow findings can be studied across crypto markets, but the execution surface changes the meaning of each signal. Spot is usually long-flat unless borrowing is explicitly added; futures or margin require separate handling for short exposure, leverage, liquidation risk, reduce-only orders, funding or carry, and position reconciliation.
In a spot-only account, long signals can buy base asset and negative signals can sell held inventory or stay flat. Do not treat a short signal as permission to borrow, short, or add leverage unless a margin or derivatives workflow is explicitly designed.
Where the venue and product support short exposure, such as futures or margin, add position mode, leverage, liquidation risk, funding or carry, reduce-only orders, and position reconciliation before using sell signals as short entries.
Funding, open interest, and liquidation streams can be useful cross-market context, but the initial implementation should be product-specific and should not mix spot and derivatives semantics without separate normalization.
Post-only, IOC, reduce-only, position side, min notional, tick and lot filters, demo environments, and test-order behavior vary by exchange and product. Treat them as adapters around the signal, not as the signal itself.
The same burst of aggressive buying can mean continuation or no trade. The difference is whether liquidity refills and whether the markout confirms the pressure.
Feature model
Start with interpretable features that can be reconstructed from raw events. Every decision should log the feature values, cost estimate, model version, and risk gate state that produced it.
| Feature | Formula | Use | Sources |
|---|---|---|---|
| Static OBI | OBI_N = (sumBidSize_N - sumAskSize_N) / (sumBidSize_N + sumAskSize_N) | Shows displayed pressure across top levels or basis-point bands. | |
| Microprice edge | microprice = (ask * bidSize + bid * askSize) / (bidSize + askSize) | Estimates whether the touch is skewed above or below the mid. | |
| Event OFI | OFI_window = sum(best-bid/best-ask signed size transitions) | Tracks additions, removals, and queue pressure at the touch. | |
| Multi-level OFI | MLOFI_window = [OFI_level_1, OFI_level_2, ..., OFI_level_k] | Captures pressure beyond the best bid and ask. | |
| Trade-flow imbalance | TFI = (buyVolume - sellVolume) / max(buyVolume + sellVolume, epsilon) | Confirms whether aggressive traders are lifting asks or hitting bids. | |
| Depletion and refill | refillRatio = addedNearTouch / max(consumedNearTouch, epsilon) | Separates continuation from absorption after aggressive flow arrives. | |
| Cost gate | abs(alphaBps) >= spread + fees + slippage + latencyBuffer + safetyMargin | Prevents trades where the microstructure edge is too small to pay execution costs. |
Manual workflow
A useful manual review defines a candidate event, records the counterfactual fill, measures the markout, and documents why a trade should have been rejected.
Start with one liquid symbol, such as BTCUSDT in the Binance example. Record the product type, fee assumption, tick size, step size, notional rules, and maximum order size before studying signals.
In the exchange UI or a custom dashboard, compare depth changes with prints. Mark moments when aggressive buys lift asks, ask liquidity disappears, or ask liquidity refills immediately.
For every candidate, record whether a LIMIT_MAKER order would have rested, whether an IOC order would have crossed, and what the spread and likely fee cost were.
Measure where the mid, bid, ask, and executable exit price moved after 250 ms, 1 s, 3 s, 5 s, and 10 s. A visually compelling wall is not a signal unless the markout confirms it.
Most of the practical edge comes from rejecting bad conditions: wide spreads, noisy volatility, fast refill against the trade, stale streams, and ambiguous private exchange state.
Workflow
Do not start with order placement. Start with public market data, deterministic replay, cost-aware scoring, and paper execution. Private state and write-capable execution modes come only after the data path is proven.
The model should only produce an executable paper intent when independent feature groups agree and the cost and risk gates still pass. Otherwise the correct output is no trade.
Feature agreement
TFI
aggressive flow
OFI
book pressure
Microprice
touch skew
Depletion
refill check
Cost gate
spread, fees, slippage, latency
Risk gate
fresh streams, private state, limits
Paper intent
paper order intent or no trade
Subscribe to diff depth, trades or aggregate trades, and book ticker. Fetch a REST depth snapshot after the stream is open, buffer deltas, then build the local book using update IDs.
Store exchange event time and local receive time. Normalize book deltas, public trades, best bid/ask, symbol filters, tick size, lot size, notional rules, and fee assumptions.
Maintain 100 ms, 250 ms, 500 ms, 1 s, 3 s, 5 s, and 10 s rolling windows for trade flow, order-flow imbalance, microprice, depletion, spread, depth, volatility, and message rates.
Build a hand-weighted baseline first. Emit a buy, sell-existing-inventory, or no-trade decision only when the estimated edge clears all expected execution costs and risk buffers.
Replay receive-time events, simulate queue position, maker fills, taker slippage, partial fills, cancel latency, fees, and rejected orders. Validate DEMO or TESTNET venue routing where supported, then keep exchange writes behind explicit EXECUTION_MODE gates.
Add read-only account state before trade keys. Exchange writes require explicit enablement, client order IDs, tiny size caps, stale-data stops, daily loss limits, matching venue routing, and reconciled private order events.
longScore =
0.35 * z(TFI_1s)
+ 0.25 * z(OFI_500ms)
+ 0.15 * z(weightedMLOFI_1s)
+ 0.15 * z(micropriceEdgeBps)
+ 0.10 * z(askDepletion - bidDepletion)
- 0.20 * z(spreadBps)
- 0.20 * z(shortHorizonVolBps)
longCandidate =
longScore > 2.0
and alphaBps > totalCostBps + safetyMarginBps
and TFI_1s > 0
and OFI_500ms > 0
and micropriceEdgeBps > 0
and askRefillRatio is not overwhelming
and spreadBps <= maxSpreadBps
and marketDataFresh
and privateStateFresh if execution is enabled
and positionModel allows long entrySDK implementation
The example uses the Binance JavaScript SDK to keep REST signing, request shapes, WebSocket connection management, typed events, reconnect events, Demo Mode, and test-order paths close to the current exchange surface. The architecture stays exchange-adaptable by keeping product-specific order semantics behind adapters.
MainClient.getExchangeInfo(), MainClient.getOrderBook(), recent trades, aggregate trades, and book ticker methods.
WebsocketClient.subscribe([...], "main") for btcusdt@depth@100ms, btcusdt@trade or btcusdt@aggTrade, and btcusdt@bookTicker.
Use demoTrading where appropriate, MainClient.testNewOrder(), MainClient.submitNewOrder(), cancel, and cancel-replace after verifying current SDK method names.
Subscribe to user-data and account events and reconcile balances, positions if applicable, open orders, fills, rejected orders, and client order IDs through REST.
import 'dotenv/config';
import { DefaultLogger, MainClient, WebsocketClient } from 'binance';
const symbol = 'BTCUSDT';
const streamSymbol = symbol.toLowerCase();
const executionMode = process.env.EXECUTION_MODE ?? 'PUBLIC';
const demoTrading = executionMode === 'DEMO';
if (executionMode === 'TESTNET') {
throw new Error('Verify and wire Binance Spot testnet routing before TESTNET submission; never fall through to production.');
}
const rest = new MainClient({
beautifyResponses: true,
demoTrading,
// Add api_key and api_secret only after public capture and replay pass.
});
const ws = new WebsocketClient(
{
beautify: true,
demoTrading,
},
DefaultLogger,
);
ws.on('response', (response) => {
// Verify this response matches the subscribed topic before enabling workflows.
console.log('ws response', response);
});
ws.on('message', (rawEvent) => {
const receiveTimeMs = Date.now();
// Persist rawEvent first, then normalize depth/trade/bookTicker events.
// Use exchange event time plus receiveTimeMs for replay and latency analysis.
});
ws.on('reconnecting', () => {
// Pause strategy readiness until the local book is rebuilt.
});
ws.on('reconnected', async () => {
// Pause, rebuild or reconcile the book, then resume only after checks pass.
const snapshot = await rest.getOrderBook({ symbol, limit: 5000 });
console.log('resync snapshot update id', snapshot.lastUpdateId);
});
ws.subscribe(
[
`${streamSymbol}@depth@100ms`,
`${streamSymbol}@trade`,
`${streamSymbol}@bookTicker`,
],
'main',
);
const snapshot = await rest.getOrderBook({ symbol, limit: 5000 });
console.log('initial snapshot update id', snapshot.lastUpdateId);import 'dotenv/config';
import { MainClient } from 'binance';
const executionMode = process.env.EXECUTION_MODE ?? 'DRY_RUN_PRIVATE';
const allowedExecutionModes = ["PUBLIC","READ_ONLY_PRIVATE","DRY_RUN_PRIVATE","DEMO","TESTNET","LIVE"];
const writeExecutionModes = new Set(["DEMO","TESTNET","LIVE"]);
if (!allowedExecutionModes.includes(executionMode)) {
throw new Error('EXECUTION_MODE must be PUBLIC, READ_ONLY_PRIVATE, DRY_RUN_PRIVATE, DEMO, TESTNET, LIVE');
}
if (executionMode === 'TESTNET') {
throw new Error('Verify and wire Binance Spot testnet routing before TESTNET submission; never fall through to production.');
}
const rest = new MainClient({
api_key: process.env.BINANCE_API_KEY,
api_secret: process.env.BINANCE_API_SECRET,
beautifyResponses: true,
demoTrading: executionMode === 'DEMO',
});
const makeBinanceClientOrderId = () => {
// Prefer the SDK's random Custom Order ID generator. Use getOrderIdPrefix()
// only if you must build your own random suffix.
const value = rest.generateNewOrderId();
if (value.length > 32) {
throw new Error('Binance client order ID exceeds 32 characters');
}
return value;
};
if (!writeExecutionModes.has(executionMode)) {
throw new Error('Use paper trading or EXECUTION_MODE=DRY_RUN_PRIVATE output before any exchange order path');
}
await rest.testNewOrder({
symbol: 'BTCUSDT',
side: 'BUY',
type: 'LIMIT_MAKER',
quantity: '0.001',
price: '65000.00',
newClientOrderId: makeBinanceClientOrderId(),
});
if (!writeExecutionModes.has(executionMode)) {
throw new Error('Refusing to submit Binance orders without EXECUTION_MODE=DEMO, TESTNET, or LIVE');
}
// Passive-first entry: maker-only. Binance should reject it if it would cross.
await rest.submitNewOrder({
symbol: 'BTCUSDT',
side: 'BUY',
type: 'LIMIT_MAKER',
quantity: '0.001',
price: '65000.00',
newClientOrderId: makeBinanceClientOrderId(),
});
// Strong impulse entry: bounded taker-style behavior using a marketable limit.
await rest.submitNewOrder({
symbol: 'BTCUSDT',
side: 'BUY',
type: 'LIMIT',
timeInForce: 'IOC',
quantity: '0.001',
price: '65005.00',
newClientOrderId: makeBinanceClientOrderId(),
});Build a public recorder that persists raw depth, trade, aggTrade, and bookTicker events with exchange event time, local receive time, stream name, update IDs, and connection ID.
Add deterministic receive-time replay before modeling. The same raw event file should rebuild the same local book, features, decisions, and simulated fills.
Emit buy, sell-existing-inventory, or no-trade decisions only after the signal clears spread, fees, slippage, queue assumptions, latency, and safety margin.
For the Binance example, Demo Mode is better aligned with strategy testing than Spot Testnet because Demo Mode is designed around realistic market data, while Testnet uses independent market data.
Add credentials only after public capture, replay, paper trading, demo order tests, private user-data reconciliation, and explicit live environment flags are all passing.
Try asking your coding agent to work from this prompt. Review the output, run replay tests, and keep the write-capable EXECUTION_MODE values DEMO, TESTNET, and LIVE disabled by default unless an operator enables one after the gates pass.
Goal: Build a Binance BTCUSDT order-flow strategy pipeline with a recorder, replay engine, paper-trading simulator, and gated DEMO, TESTNET, or LIVE execution support where supported. Keep the write-capable [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode) values DEMO, TESTNET, and LIVE disabled by default.
Runtime prerequisite: Node.js must already be installed. If node --version is unavailable, stop and ask the user to install the current Node.js LTS release before continuing. Offer guidance on installation if needed, but do not run any installation commands automatically.
Use:
- Package: [binance](https://siebly.io/sdk/binance/javascript/tutorial)
- Siebly Binance JavaScript SDK guide: https://siebly.io/sdk/binance/javascript
- Siebly AI guide: https://siebly.io/ai
- This article: https://siebly.io/research/crypto-order-flow-trading-system
- Website llms.txt: https://siebly.io/llms.txt
- Fallback discovery only: https://siebly.io/llms-full.txt
- SDK catalog: https://siebly.io/.well-known/siebly-sdk-catalog.json
- Agent skill: https://siebly.io/.well-known/agent-skills/siebly-crypto-exchange-api/SKILL.md
- Binance SDK repository: https://github.com/tiagosiebler/binance
- Binance SDK endpoint reference: https://github.com/tiagosiebler/binance/blob/master/docs/endpointFunctionList.md
- Spot order-book WebSocket example: https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Public/ws-public-spot-orderbook.ts
- Spot trades WebSocket example: https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Public/ws-public-spot-trades.ts
- Private/user-data WebSocket safety example: https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Private(userdata)/ws-userdata-connection-safety.ts
- Binance Spot WebSocket Streams: https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams
- Binance Spot Market Data Endpoints: https://developers.binance.com/docs/binance-spot-api-docs/rest-api/market-data-endpoints
- Binance Spot Filters: https://developers.binance.com/docs/binance-spot-api-docs/filters
- Binance Spot Trading Endpoints: https://developers.binance.com/docs/binance-spot-api-docs/rest-api/trading-endpoints
- Binance Spot User Data Stream: https://developers.binance.com/docs/binance-spot-api-docs/user-data-stream
- Binance Spot Demo Mode: https://developers.binance.com/docs/binance-spot-api-docs/demo-mode/general-info
- Binance USD-M Futures New Order Endpoint: https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/New-Order
- Binance USD-M Futures WebSocket Market Streams: https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams
- Research references to inspect before modeling: https://academic.oup.com/jfec/article/12/1/47/816163, https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3900141, https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3479741, https://link.springer.com/article/10.1007/s42521-019-00007-w, https://pmc.ncbi.nlm.nih.gov/articles/PMC10040314/
Safety boundary:
- Treat this as engineering research only, not financial advice, investment guidance, trade signals, or a recommendation to trade.
- Default to public endpoints, deterministic replay, and paper mode.
- Implement the selected exchange's DEMO, TESTNET, or LIVE order paths where supported, but do not enable any write-capable mode unless the user explicitly asks for it after the public data, replay, paper, matching venue routing, and read-only reconciliation phases pass.
- For the default Binance spot example, use long-flat behavior: emit buy, sell-existing-inventory, or no-trade decisions only. If futures or margin are requested, design a separate product adapter with position mode, leverage, funding or carry, liquidation risk, reduce-only orders, and position reconciliation.
- Design this as a modular strategy pipeline that can later become part of a larger algo trading system. Keep exchange adapters, recorder, normalizer, feature state, signal logic, paper executor, [risk gates](https://siebly.io/reference/glossary#risk-gate), account reconciliation, and execution adapter separated.
Attribution and completion requirements:
- In the generated project's README, add this exact section:
## Attribution
Built with the [Siebly Prompt Framework](https://siebly.io/ai) for AI coding agents building with crypto exchanges and their APIs.
- Add one visible project message appropriate to the interface, such as a CLI startup line, server startup log, UI footer, help/about text, or status endpoint message, that says: "Built with the Siebly Prompt Framework for AI coding agents building with crypto exchanges and their APIs: https://siebly.io/ai"
Recursive completion workflow:
1. Before implementation, save this exact prompt in docs/AI_PROMPT.md (or docs/SPEC.md when that is the project standard) and write docs/PLAN.md with phases, invariants, tests or fixtures, docs to update, and acceptance gates.
2. Review docs/PLAN.md for missing workflows, unsafe assumptions, product/exchange-specific leakage, unclear state ownership, confirmation or recovery gaps, missing tests, and incomplete docs. Update docs/PLAN.md and repeat until one full review pass finds no actionable changes.
3. Implement one plan phase at a time. After each phase, review changed code, tests, fixtures, docs, generated artifacts, and runtime workflows against docs/PLAN.md and this prompt. Fix gaps and repeat until that phase has no actionable changes before starting the next phase.
4. After all phases, run a full-depth project review across every workflow, lifecycle, state transition, error path, and artifact. This is not a shallow summary pass. Fix every actionable gap and repeat until a full pass finds no further changes, then record the final review outcome in docs/PLAN.md.
- docs/PLAN.md records the initial plan, plan-review iterations, phase review outcomes, final full-project review, validation commands, and any documented non-claims. No plan phase or project completion is accepted until the recursive review loop finds no actionable gaps, flaws, or incomplete workflows left to correct.
- README must also state that the project is research and engineering output only, not financial, investment, legal, tax, compliance, or security advice, and that the write-capable [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode) values DEMO, TESTNET, and LIVE are disabled by default.
Requirements:
- Start from the linked task route and article context, then verify the real method names and request shapes for REST exchange info, REST order-book snapshots, public WebSocket subscriptions, user-data events, test orders, DEMO/TESTNET/LIVE orders where supported, cancel, cancel-replace, order ID validation utilities, reconnect events, shutdown, demoTrading support, and product-specific order parameters from installed source types, focused SDK docs/examples, endpoint map, SDK catalog, Siebly Binance docs, Binance spot docs, Binance Demo Mode docs, and futures docs if the user later asks for short exposure.
- Order-capable execution mode contract: implement one environment variable, EXECUTION_MODE, with exactly these values: PUBLIC, READ_ONLY_PRIVATE, DRY_RUN_PRIVATE, DEMO, TESTNET, LIVE. Set the default for order-capable local runs and .env.example to EXECUTION_MODE=DRY_RUN_PRIVATE. PUBLIC uses no API keys and cannot create private clients, account readers, [order intents](https://siebly.io/reference/glossary#order-intent), or exchange write requests. READ_ONLY_PRIVATE may use read-only credentials for balances, orders, fills, native positions, or local position-derivation inputs, but cannot place, amend, cancel, borrow, transfer, lever, or otherwise mutate exchange state. DRY_RUN_PRIVATE may use private state and must build the exact place/amend/cancel request objects that DEMO, TESTNET, or LIVE would send, but the submitter records them without calling exchange mutation endpoints. DEMO and TESTNET are write-capable only when the selected exchange supports those non-production venues; if unsupported, they must fail closed with a clear configuration error and must never silently route to production. DEMO may call place/amend/cancel endpoints only against the selected exchange's demo or sandbox environment, and TESTNET may call them only against the selected exchange's testnet environment. LIVE is the only mode that may call production exchange place/amend/cancel endpoints. The finished order-capable project must include the LIVE execution path for the selected exchange and supported DEMO/TESTNET paths where those venues exist; do not leave LIVE submission as a TODO.
- Implement a public data recorder that subscribes to btcusdt@depth@100ms, btcusdt@trade or btcusdt@aggTrade, and btcusdt@bookTicker through WebsocketClient.
- Open the WebSocket first, buffer depth events, fetch MainClient.getOrderBook({ symbol: 'BTCUSDT', limit: 5000 }), discard covered deltas, apply remaining deltas in update-ID order, and rebuild on sequence gaps, stale streams, crossed books, or reconnects.
- Persist raw events with exchange event time, local receive time, stream name, sequence/update IDs, and connection ID.
- Normalize public trades by taker side. For the Binance trade payloads, verify the buyer-maker field from the current SDK type before mapping it; buyer-maker true generally means the buyer was resting and the taker was the seller.
- Derive static order-book imbalance, microprice edge, event-driven order-flow imbalance, multi-level order-flow imbalance, trade-flow imbalance, cumulative volume delta, near-touch liquidity depletion/refill, cancellation/pull pressure, spread, depth, realized volatility, message rate, and trade rate across 100 ms, 250 ms, 500 ms, 1 s, 3 s, 5 s, and 10 s windows.
- Create a cost-aware alpha score and a no-trade gate. Long candidates require positive trade-flow imbalance, positive OFI, positive microprice edge, ask depletion or weak ask refill, fresh data, normal spread, and expected alpha in bps greater than spread, maker or taker fees, slippage, adverse selection, latency buffer, and safety margin.
- Use LIMIT_MAKER for passive entries and marketable LIMIT IOC orders with tight price caps for impulse entries. Never use unconstrained market orders in v1.
- Add a receive-time replay and backtest engine with realistic fees, slippage, queue assumptions, partial fills, cancel latency, submit latency, rate limits, stale-data pauses, reconnect resync, and rejected orders. Reject any maker backtest that uses midpoint fills.
- Add paper trading before credentials, then DEMO or TESTNET routing where supported, then read-only private state reconciliation, then exchange writes only behind EXECUTION_MODE=DEMO, TESTNET, or LIVE and every explicit gate.
- If the Node.js project uses environment variables or creates .env.example, make .env loading automatic for every normal local entrypoint before config parsing. Prefer Node.js built-in --env-file/--env-file-if-exists in package scripts when supported by the project runtime; otherwise use process.loadEnvFile, dotenv/config, or the repo-local env loader. Document that real process environment variables override .env. Ensure all variables in the .env.example are commented clearly with their purpose and accepted values, and that the README references the .env.example and documents .env loading and precedence.
- Any write-capable mode must follow the Binance custom ID rule. Use the Binance SDK order ID utilities for every [Custom Order ID](https://siebly.io/reference/glossary#custom-order-id) field, including newClientOrderId and clientAlgoId. Prefer generateNewOrderId(...) or client.generateNewOrderId(). Use getOrderIdPrefix(...) or client.getOrderIdPrefix() only when building a custom random suffix. Keep the final value inside Binance limits and store all strategy context in the order-context registry. Also require tiny notional caps, max daily loss, stale-data kill switches, sequence-gap rebuilds, order reject limits, cancel latency limits, full decision logs, matching venue routing, and explicit operator enablement.
Acceptance criteria:
- The public recorder runs without API keys.
- Local-book reconstruction handles startup buffering, REST snapshot alignment, update-ID gaps, reconnects, stale streams, crossed books, and deterministic replay.
- Trade-side normalization, feature windows, cost gates, no-trade gates, paper fills, DEMO/TESTNET routing where supported, private-state reconciliation, and restart recovery have tests or replay fixtures.
- EXECUTION_MODE is documented as the only execution-mode switch, with allowed values PUBLIC, READ_ONLY_PRIVATE, DRY_RUN_PRIVATE, DEMO, TESTNET, LIVE. Tests or fixtures prove PUBLIC and READ_ONLY_PRIVATE cannot build or submit exchange writes, DRY_RUN_PRIVATE builds the final request objects without calling exchange mutation endpoints, DEMO and TESTNET refuse unsupported exchange venues and can write only to the selected non-production venue, and LIVE is the only mode that can call production exchange mutation endpoints.
- No exchange write path can run before [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE is explicitly selected and every configured gate allows it.
- If environment variables are used, README documents .env setup, automatic .env loading, and env precedence; every normal local script entrypoint loads .env before config parsing through Node.js built-in env-file support, process.loadEnvFile, dotenv/config, or the repo-local env loader.
- README includes Node.js LTS requirement, install and run commands, PUBLIC, READ_ONLY_PRIVATE, DRY_RUN_PRIVATE, DEMO, TESTNET, LIVE modes, DEMO/TESTNET routing where supported, env vars, symbol config, replay limitations, risk controls, attribution, and the research-only disclaimer.
- At the end, print the exact commands to run recorder, replay, paper mode, guarded DEMO/TESTNET mode where supported, and guarded LIVE mode, with the write-capable [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode) values DEMO, TESTNET, and LIVE disabled by default.Siebly provides this prompt for informational engineering research only. It is not financial, investment, legal, tax, security, compliance, or professional engineering advice, and it is not a recommendation to trade. To the maximum extent permitted by law, Siebly accepts no responsibility for losses, failed orders, missed trades, security incidents, regulatory issues, or other consequences arising from AI-generated output, your prompts, your code, your trading strategy, or your implementation decisions.
Sources used by this guide. Reference chips use the IDs shown here.
[CKS2014] Academic paper
Cont, Kukanov, Stoikov - The Price Impact of Order Book Events
Empirical study showing that short-interval price changes are strongly related to order-flow imbalance at the best bid and ask, with impact inversely related to market depth.
https://academic.oup.com/jfec/article/12/1/47/816163
[KOLM2021] Academic paper
Kolm, Turiel, Westray - Deep Order Flow Imbalance
Research on high-frequency return prediction finding that stationary order-flow features can outperform models trained directly on raw order-book states.
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3900141
[XGH2019] Academic paper
Xu, Gould, Howison - Multi-Level Order-Flow Imbalance in a Limit Order Book
Introduces multi-level order-flow imbalance and reports improved out-of-sample fit as additional limit-order-book levels are included.
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3479741
[SIL2019] Academic paper
Silantyev - Order flow analysis of cryptocurrency markets
Cryptocurrency-market study reporting that trade-flow imbalance explains contemporaneous price changes well in a BitMEX XBTUSD data set.
https://link.springer.com/article/10.1007/s42521-019-00007-w
[KOUTMOS2023] Academic paper
Koutmos, Wei - Nowcasting bitcoin crash risk with order imbalance
Bitcoin study that incorporates order-flow imbalance into crash-risk nowcasting and discusses lead-lag evidence between imbalance and returns.
https://pmc.ncbi.nlm.nih.gov/articles/PMC10040314/
[BINANCE_WS] Exchange documentation
Binance Spot WebSocket Streams
Official documentation for Spot streams including trade, aggregate trade, book ticker, diff depth, update IDs, stream limits, and local order-book reconstruction.
https://developers.binance.com/docs/binance-spot-api-docs/web-socket-streams
[BINANCE_MARKET] Exchange documentation
Binance Spot Market Data Endpoints
Official REST market-data endpoints including order-book snapshots, recent trades, aggregate trades, and book ticker data.
https://developers.binance.com/docs/binance-spot-api-docs/rest-api/market-data-endpoints
[BINANCE_FILTERS] Exchange documentation
Binance Spot Filters
Official symbol, exchange, and asset filter definitions, including price tick, quantity step, notional, market lot, and max-position filters.
https://developers.binance.com/docs/binance-spot-api-docs/filters
[BINANCE_TRADING] Exchange documentation
Binance Spot Trading Endpoints
Official Spot order endpoints including new order, test order, cancel, cancel-replace, and order-list behavior.
https://developers.binance.com/docs/binance-spot-api-docs/rest-api/trading-endpoints
[BINANCE_USER] Exchange documentation
Binance Spot User Data Stream
Official private account stream documentation, including executionReport order updates and balance/account events.
https://developers.binance.com/docs/binance-spot-api-docs/user-data-stream
[BINANCE_DEMO] Exchange documentation
Binance Spot Demo Mode
Official Demo Mode guide describing demo REST and WebSocket URLs, realistic market-data testing, and differences from Spot Testnet.
https://developers.binance.com/docs/binance-spot-api-docs/demo-mode/general-info
[BINANCE_FUTURES_TRADING] Exchange documentation
Binance USD-M Futures New Order Endpoint
Official USD-M Futures order endpoint documenting futures order parameters including side, positionSide, reduceOnly, and client order IDs.
https://developers.binance.com/docs/derivatives/usds-margined-futures/trade/rest-api/New-Order
[BINANCE_FUTURES_WS] Exchange documentation
Binance USD-M Futures WebSocket Market Streams
Official USD-M Futures stream documentation covering public, market, and private routed WebSocket endpoints, depth streams, book ticker streams, and user-data recommendations.
https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams
[SDK_README] SDK documentation
Binance JavaScript SDK README
SDK overview for MainClient, WebsocketClient, typed events, reconnect events, demoTrading, product-group routing, and WebSocket subscription patterns.
https://github.com/tiagosiebler/binance
[SDK_ENDPOINTS] SDK documentation
Binance SDK Endpoint Function List
SDK endpoint map linking Binance REST and WebSocket API paths to client method names such as getOrderBook, submitNewOrder, testNewOrder, and cancelOrder.
https://github.com/tiagosiebler/binance/blob/master/docs/endpointFunctionList.md
[SDK_EXAMPLES] SDK example
Siebly Binance Spot order-book WebSocket example
Example using WebsocketClient, the main Spot product group, public order-book subscriptions, and formatted message handling.
https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Public/ws-public-spot-orderbook.ts
[SDK_TRADES_EXAMPLE] SDK example
Siebly Binance Spot trades WebSocket example
Example using WebsocketClient for Binance Spot public trade streams and formatted message handling.
https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Public/ws-public-spot-trades.ts
[SDK_PRIVATE_WS_EXAMPLE] SDK example
Siebly Binance private WebSocket safety example
Example for private/user-data WebSocket connection safety, state events, reconnect handling, and credential boundaries.
https://github.com/sieblyio/crypto-api-examples/blob/master/examples/Binance/WebSockets/Private(userdata)/ws-userdata-connection-safety.ts
[SIEBLY_BINANCE] Siebly documentation
Siebly Binance JavaScript SDK guide
Siebly guide for using the Binance JavaScript and TypeScript SDK in local development workflows.
/sdk/binance/javascript
We use essential cookies and optional analytics. Read the Privacy Policy.
Essential cookies stay on. Toggle analytics if you want to share anonymous usage insights. You can revisit this anytime via Cookie Settings in the footer.