Skip to content

Reassigning an input.time value can narrow it to 32 bits and wrap the timestamp #321

Closed

Description

@luisleo526

Summary

A time value from input.time can be narrowed to a 32-bit integer when the variable is reassigned. The full millisecond timestamp then wraps to a wrong, often negative value.

Reproduction

//@version=6
strategy("Changed time input")
int x = input.time(timestamp("01 Apr 2025 00:00 +0000"), "d")
if bar_index % 2 == 0
    x += 1000
plot(x)

The expected value is the selected timestamp, plus 1,000 milliseconds on bars where the assignment runs. The generated code instead declares x as a 32-bit int. The same narrowing is confirmed for direct reassignment and for persistent var int variables updated on later bars.

Affected versions and scope

Confirmed in PineForge Codegen 1.9.1 and on the current main branch, from which 1.10.0 is being built. Earlier affected versions have not been established for this report.

The common date-range filter using an unchanged plain time input, such as time >= startTime, is unaffected. The checked unchanged plain input variables retain 64-bit storage. Storing and changing values from timestamp(...) or time is also unaffected in the checked controls.

The narrowing is confirmed from emitted code. In one measured test strategy that used such a variable as a date-range start filter, 45 of 132 trades were opened before the selected start date (none expected). This is one example, not a bound for other scripts.

Workaround and fix

No workaround has been verified against output for this report. The fix is planned for an upcoming release (1.10.1), alongside #285. This issue remains open until the fix is verified and merged.

Release-note entry

Time inputs can wrap in variables that are changed

If a script stores an input.time value in a variable and later changes that variable, the transpiler stores it as a 32-bit integer. A time value in milliseconds since 1970 can then wrap to an incorrect, often negative number. This affects assignments such as x += …, x := …, and a var int x updated on later bars.

A time input kept in an ordinary (non-var) variable that is never changed is not affected, including the usual time >= startTime date-range filter. Whether a var variable holding an unchanged time input is affected is still being checked. Values from timestamp(...) or time that are stored and later changed are also not affected.

Trade impact: in one test strategy that used such a variable as the start of a date-range filter, 45 of its 132 trades were opened before the selected start date (none were expected). In a separate test, the usual unchanged-input date filter kept all 86 of its trades inside the range.

This is confirmed in the released transpiler 1.9.1 and in 1.10.0. No workaround has been verified yet. A fix is planned for 1.10.1.

Activity

  1. luisleo526 commented on Nov 3, 2026

    @luisleo526
    ContributorAuthor

    Fixed in #322, which is merged to main and ships in 1.10.0.

    What changed: a Pine int that holds a time input (input.time) is now held in a 64-bit integer when the time input is changed later in the script (x += ..., x := ...), when it is kept in a var variable (changed or not), and when it is copied into another variable (observed = x, y = x, a copy that is then changed), so the timestamp keeps its full millisecond value instead of wrapping to a negative number. The usual date-range shape, a time input kept in an ordinary variable and used directly (startTime = input.time(...) compared with time), stays 64-bit, as before.

    Checks that ran: 54 behaviour tests run the generated strategy and compare the value of the variable with the timestamp computed independently in the same script (changed typed and untyped, var typed and untyped, copies typed and untyped, a var input compared with the bar time, and a late assignment); they fail on the previous version and pass now, and the controls for the usual date-range shape pass on both. For the two tests of an ordinary (non-var) variable that is changed, only the first bar is compared, because later bars also depend on a separate, still open defect (such a variable is not restarted from its input on each bar). The reproduction from this issue now declares int64_t x. No other generated code in 188 reference sources changed, and a comparison of 110 recorded TradingView scripts shows 65 now equal where the previous version differed, 20 equal on both, and none worse.

    Thank you for the report. If you still see a wrapped time value after updating, please reopen with the script.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions