Skip to content
All strategies

Strategies

FMZ 'High-Frequency Harvester No.1' (Zero, fmz.com/strategy/6237) port: four-layer long-inventory passive quote ladder on BTCUSDT.BINANCE 1m, with book-depth pricing replaced by fixed relative offsets

Outcome: Verifying

FmzHighFrequencyHarvesterLadderBtc1m

FMZ 'High-Frequency Harvester No.1' (Zero, fmz.com/strategy/6237) port: four-layer long-inventory passive quote ladder on BTCUSDT.BINANCE 1m, with book-depth pricing replaced by fixed relative offsets

Hypothesis

Port of the FMZ open-source strategy '高频收割机一号' by Zero (https://www.fmz.com/strategy/6237, JavaScript, 708 copies). Credit: the strategy is by Zero. Its claimed performance is treated as unverified. WHAT THE ORIGINAL DOES: it is a spot, inventory-based, passive quasi-market-maker written for a ~2014 CNY BTC exchange (OKCoin/Huobi era, zero trading fees, 3-second polling, websocket depth). Every 3 s (SleepPeriod=3000 ms) it reads the order book and computes a buy price and a sell price for each of 4 layers i=0..3.……Show moreShow less

Port of the FMZ open-source strategy '高频收割机一号' by Zero (https://www.fmz.com/strategy/6237, JavaScript, 708 copies). Credit: the strategy is by Zero. Its claimed performance is treated as unverified. WHAT THE ORIGINAL DOES: it is a spot, inventory-based, passive quasi-market-maker written for a ~2014 CNY BTC exchange (OKCoin/Huobi era, zero trading fees, 3-second polling, websocket depth). Every 3 s (SleepPeriod=3000 ms) it reads the order book and computes a buy price and a sell price for each of 4 layers i=0..3. The inputs are: DicAmount=0.6,1.5,1.8,1.9 BTC (layer order size), DicBuyOffset=1.5,2.5,4.5,8 CNY (min distance of the buy below the layer's sell reference), DicSellOffset=1,1.8,2.5,4 CNY (min distance of the sell above the buy reference), DicResetDiff=0.1,0.3,0.3,0.4 CNY (re-quote tolerance), DicStep=9,12,17,25 BTC (depth increment for walking the book), and DicSleep=1,2,3,5 (a layer is only re-quoted on loop counts divisible by this). getOrderPrice(book, limitAmount, ownPrevPrice, defRatio) walks the book from the top, skips the level equal to the layer's own resting price, and returns the first level where cumulative size exceeds limitAmount. If it runs within 2 levels of the end of the book it returns books[1].Price*0.99 for bids or *1.01 for asks, with flag=false. buyPrice_i = getOrderPrice(bids, Amount_i) + U(0,0.03), sellPrice_i = getOrderPrice(asks, Amount_i) - U(0,0.03). The sell is then pushed deeper, walking asks with amount += Step_i until (newSell - buyPrice_i) > SellOffset_i or the flag is false. The buy is pushed deeper symmetrically until (sellPrice_i - newBuy) > BuyOffset_i. Prices are rounded to 2 dp. Each loop: updateOrders() marks filled or vanished orders as empty slots and cancels any stray orders. On loop count>0 with count % Sleep_i == 0, it cancels layer i's resting buy (or sell) if |new target - resting price| > ResetDiff_i. Then for each empty buy slot it places buy amount = min(freeCash/price, Amount_i) if >= 0.01 BTC and reduces freeCash by (price+1)*amount. For each empty sell slot, if free BTC >= 0.01, it places sell amount = min(freeBTC, Amount_i) and reduces freeBTC. At start it cancels everything and rescales Amount_i by ratio = totalEquity/2/price/sum(Amount), so the total ladder size is half of equity expressed in BTC. It NEVER shorts: it can only sell BTC it already holds. There is no stop, no take-profit and no trend logic; the profit is meant to come from buy-low/sell-high layer fills, and the inventory carries full BTC beta. The chart and log code is display-only and is not ported. PLATFORM TRANSLATION (each deviation is forced by our data): (1) Our catalog has NO historical L2 book, quote-tick or book-ticker history for BTC. order_book_delta/BTCUSDT.BINANCE is one snapshot and quote_tick has 2 files, so the depth walk cannot be replayed. The book-walk result is replaced by fixed relative offsets from the 1m bar close. These are the CNY offsets converted at a 2,000 CNY/BTC reference price, the order of magnitude when the script was published: buy_i = close*(1 - b_i) with b = [7.5, 12.5, 22.5, 40] bps, and sell_i = close*(1 + s_i) with s = [5, 9, 12.5, 20] bps. ResetDiff becomes r = [0.5, 1.5, 1.5, 2.0] bps of price. The ±0.03 CNY random jitter is dropped (0.15 bp, sub-tick, and it would make the backtest non-deterministic). DicStep has no role without a book and is dropped. (2) The 3 s poll becomes the 1-minute bar, and the loop counter becomes the bar index, so the DicSleep cadence 1,2,3,5 is in bars. (3) Venue is BINANCE USD-M perp BTCUSDT.BINANCE at leverage 1.0 with the original's no-short inventory rule enforced, which makes it economically a spot inventory (funding is paid or received on the long inventory). All quotes are post-only LIMIT orders so the 0.02% maker fee applies (0.04% round trip). The original assumed zero fees. On BINANCE_SPOT the 0.10% maker fee (0.20% RT) would kill every layer whose buy+sell distance is under 20 bp, meaning layers 1-2, before any test, so spot would not be a fair test of the mechanism. BTC is used despite its corpus concentration because the original is a BTC ladder and a passive-quote mechanism needs the deepest book. (4) The platform account starts 100% USDT. The original's ratio assumes a mixed account; as written, sells only happen after buys fill, so no initial BTC is pre-bought (faithful to the code path). Amount_i = weights [0.6, 1.5, 1.8, 1.9]/5.8 * (equity/2/close) BTC, computed once on the first bar as the original does. Minimum order 0.01 BTC as written (above the $5 notional floor). HONEST PRIOR: this is the same mechanism family as the already-abandoned 'FMZ 2014 Depth-Reach quasi-market-maker on 1m bars' (no_edge), and lesson L167 flags faithful FMZ ports. It is submitted because the user explicitly asked for a faithful port. The pre-registered numbers below predict failure: bar-resolution fills are optimistic about queue position, and the ladder's gross capture is dominated by adverse selection (layers fill in the direction price keeps moving).

Implementation

Stratmill translation of FMZ 6237 'High-Frequency Harvester No.1' (Zero): a 4-layer long-inventory passive ladder on BTCUSDT.BINANCE 1m. Each layer rests a post-only GTC buy at close*(1-b_i) and, once inventory exists, a reduce-only post-only sell at close*(1+s_i) (b=[7.5,12.5,22.5,40] bp, s=[5,9,12.5,20] bp). Layer i is re-quoted on minute indices divisible by Sleep_i=[1,2,3,5] when its target moves more than ResetDiff_i=[0.5,1.5,1.5,2] bp. Layer sizes are weights [0.6,1.5,1.8,1.9] scaled so the whole ladder equals half of equity in BTC. The strategy never shorts and has no stop, take-profit or trend logic.

Iteration 3: the Layer-1 'invalid decimal literal at line 1' came from the previous output putting a placeholder path string in `code` instead of the Python source. The strategy source is unchanged from iteration 2 (the performance fix: in-place modify_order re-quotes, O(layers) per bar) apart from a docstring note, and is now submitted inline. Port deviations, all forced by missing data: there is no historical L2 book, so the depth walk is replaced by fixed bp offsets (the CNY offsets at 2,000 CNY/BTC); the 3 s loop is the 1m bar; the loop counter is the calendar minute index so re-quotes survive restarts; the random jitter and DicStep are dropped; quotes are post-only makers on a USD-M perp at 1x with no shorting. Honest prior: this mechanism family has been abandoned before for no_edge, and bar-resolution fills are optimistic about queue position. Adverse selection is expected to dominate.

Verification Results

Verification failed (Layer 2 — synthetic scenarios): Parameters used: ['sleep_bars', 'min_order_qty', 'amount_weights', 'buy_offset_bps', 'reset_diff_bps', 'cash_buffer_bps', 'sell_offset_bps', 'ladder_equity_frac'] Check that __init__ sets all attributes from self.parameters.get(). - steady_uptrend: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000) - steady_downtrend: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000) - flat_ranging: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000) - volatility_spike: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000) - zero_volume: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000) - price_gap: AttributeError: '_MockCache' object has no attribute 'orders_open_count' (bar timestamp: 1735689660000)

Iteration History

sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (30 days of BTCUSDT.BINANCE-1-MINUTE-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).

Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)

Analysis

高频收割机一号

Backtest and paper results are hypothetical. Trading involves risk of loss.