Skip to content

Known issues in PineForge Engine 1.9.1: order quantities #716

Open

Description

@luisleo526

The following issues affect the released 1.9.1 version. The examples are minimal trigger patterns for crypto charts.

  1. An entry with qty=na can be missing entirely. qty=na uses the strategy's default quantity; the example below selects 100% of equity. In the measured BTCUSDT case, TradingView computes that quantity using the signal bar's close, truncates it to the symbol's quantity step, and leaves the order unfilled if that quantity cannot be funded at the fill price. Version 1.9.1 does not apply that truncation in this run, so some orders that are just over the available equity at the fill are declined and their trades are missing.

    //@version=6
    strategy("Entry quantity example", currency=currency.NONE,
        default_qty_type=strategy.percent_of_equity, default_qty_value=100)
    if bar_index == 1
        strategy.entry("L", strategy.long, qty=na)
    

    An explicit quantity instead of na places the entry on 1.9.1, measured on one source. This selects a quantity explicitly; it does not reproduce all-equity sizing. The explicit-quantity variant of the literal example above has not been measured.

  2. An order quantity can retain extra digits. In the measured BTCUSDT 1-hour cases, TradingView truncates quantity down to the symbol's quantity step; it does not round. The affected engine keeps the extra digits. At BTC around 45,000, the observed last-digit difference is about 0.45 USDT of position and a few cents of PnL per trade. This comparison does not establish behavior for every symbol.

    Use a crypto chart whose quantity step is coarser than the explicit quantity in this pattern:

    //@version=6
    strategy("Quantity step example", currency=currency.NONE)
    if bar_index == 1
        strategy.entry("L", strategy.long, qty=0.123456789)
    

    Workaround: not yet verified.

A fix ships in the next release (1.10.0). No release date is announced here.

Updated 2026-11-03: this issue first said "the next patch release". The next release is 1.10.0, a minor release.

Activity

  1. luisleo526 commented on Nov 3, 2026

    @luisleo526
    CollaboratorAuthor

    Partially addressed by #727 (9fa1ac5): the engine floors order quantities to a declared qty_step, or to mincontract when no qty_step is declared. Runs that declare neither key remain unchanged. This issue stays open for the remaining caller metadata and quantity cases.

  2. luisleo526 commented on Nov 3, 2026

    @luisleo526
    CollaboratorAuthor

    v1.10.0 is released and includes the quantity-step part of this issue: it supplies a quantity step for library callers that set only the minimum order size, and an explicit quantity step takes precedence (https://github.com/pineforge-4pass/pineforge-engine/releases/tag/v1.10.0). Symbols without a lot size remain gridless; that part is planned for the next release (1.10.1).

  3. luisleo526 commented on Nov 7, 2026

    @luisleo526
    CollaboratorAuthor

    Status: the fix is in review and planned for the 1.11.0 release. This issue stays open until the fix is on main; we will close it then with the commit that fixes it.

  4. luisleo526 commented on Nov 9, 2026

    @luisleo526
    CollaboratorAuthor

    Status at v1.11.0: both items are fixed for runs that declare a quantity step (qty_step, or mincontract when no qty_step is declared): the engine floors order quantities to it since v1.10.0 (#727, commit 9fa1ac5), and v1.11.0 keeps that. Runs that declare neither key are unchanged, as #727 described. This issue stays open for that case; we will post here when it is closed.

  5. letiep97 commented on Nov 10, 2026

    @letiep97

    One more quantity case, measured on v1.11.0 and v1.10.0 with a declared qty_step (0.00001, mincontract 0.00001).

    When the qty passed to strategy.close() is not a multiple of the quantity step, PineForge places no closing order at all. TradingView floors the quantity to the step and closes that much, as item 2 of this issue describes for entries.

    //@version=6
    strategy("close a quantity finer than the quantity step", overlay = true, initial_capital = 10000)
    size = 0.03683
    if ta.crossover(ta.ema(close, 10), ta.ema(close, 30))
        strategy.entry("Long", strategy.long, qty = size)
    if strategy.position_size == size and close > strategy.position_avg_price * 1.005
        strategy.close("Long", qty = strategy.position_size * 0.5)
    if ta.crossunder(ta.ema(close, 10), ta.ema(close, 30))
        strategy.close("Long")
    

    Half of 0.03683 is 0.018415. Control: size = 0.03682, whose half is 0.01841.

    Generated call (Codegen 1.11.0): strategy_close(std::string("Long"), "", (signed_position_size() * 0.5), na<double>(), false, 30064771091ULL);

    Script (0.03683) Control (0.03682)
    TradingView 44 trades: where the partial close fires it takes 0.01841, and the rest closes later as 0.01842 44 trades: 0.01841 and 0.01841
    PineForge v1.11.0 and v1.10.0 26 trades: no partial close ever fills, every entry closes whole at 0.03683 44 trades, the same closed trades as TradingView

    First entry, 2024-01-04 17:00 at 43915.70: TradingView closes 0.01841 on 2024-01-04 22:00 at 44430.86 and the remaining 0.01842 on 2024-01-05 17:00 at 43225.99; PineForge closes 0.03683 on 2024-01-05 17:00 at 43225.99.

    Setup: BTCUSDT 1h bars from 2024-01-01 to 2024-03-01 (1,441 bars), initial capital 10000, no commission or slippage, mintick 0.01, Apple clang 17.0.0, macOS 15.8 arm64. TradingView: BINANCE:BTCUSDT 1h, Deep Backtesting over the same dates, measured on 2026-11-10; its 44 trades are 43 closed and one open at the end of the range.

    Workaround: strategy.close("Long", qty_percent = 50) instead of a computed qty. With it PineForge v1.11.0 gives TradingView's trades for the 0.03683 script (0.01841, then 0.01842).

  6. luisleo526 commented on Nov 13, 2026

    @luisleo526
    CollaboratorAuthor

    Status 2026-11-13: one item is fixed on main (merged today): a closing quantity that is not a multiple of the quantity step is floored to the step and the position closes, as TradingView does. It ships in 1.13.0 (planned 2026-11-15). We confirm by 2026-11-14 which of the other items in this issue that change also covers, close what is complete, and give a date for anything left.

    🤖 Generated with Claude Code

  7. luisleo526 commented on Nov 14, 2026

    @luisleo526
    CollaboratorAuthor

    Status 2026-11-14: the fix for this issue is in final verification (a lab run on the release build). It ships in PineForge 1.13.0 (release 2026-11-16), and this issue closes when it merges.

  8. added a commit that references this issue on Nov 14, 2026
  9. luisleo526 commented on Nov 14, 2026

    @luisleo526
    CollaboratorAuthor

    Update 2026-11-14: one more part of this issue is fixed on main in ecc3348: an oca.cancel order that fills completely now cancels its sibling orders again after quantity normalization. This joins the closing-quantity fix merged on 2026-11-13 (a closing quantity that is not a multiple of the quantity step is floored to the step, and the position closes, as TradingView does). Both ship in PineForge 1.13.0 (release planned 2026-11-16).

    A correction to our status comment earlier today: this issue does NOT close on this merge. The remaining part, quantity truncation to the symbol's quantity step for entries (items 1 and 2 above), is in the last engine change set for 1.13.0 (merge cut-off 2026-11-15). This issue closes when that merges, and we post here when it does. If it misses 1.13.0, we say so here the same day.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions