Coming from Pine Script
XFlow Script reads like Pine Script on purpose, and most indicators port line by line. These are the differences that matter.
| Pine Script | XFlow Script |
|---|---|
| //@version=6 and indicator("Name", overlay=true) | //@xfscript 1 and indicator("Name"). Price drawings go on the chart, and panel drawings open the sub panel by themselves. |
| Indented blocks | Braces, the opening brace on the same line: if close > open { } |
| A call wrapped over several lines | Not allowed: every call on one line |
| x = 1 and x := 2 | let x: float = 1 for a value recomputed on every bar; var x: float = 1 and x := 2 for one that carries forward |
| cond ? a : b, for i = 0 to n, while, break, continue, += | The same |
| na, na(x), nz(x), hl2, hlc3, ohlc4, hlcc4 | The same |
| input.int(14, "Length") | input.int(14, "length", "Length", 1, 500, 1): the key the setting is saved under, the title, then optional bounds and step |
| ta.sma, ta.ema, ta.wma, ta.hma, ta.vwma, ta.alma, ta.rsi, ta.atr, ta.tr, ta.stoch, ta.cci, ta.mfi, ta.cmo, ta.mom, ta.roc, ta.cum, ta.highest, ta.lowest, ta.change, ta.crossover, ta.crossunder, ta.cross, ta.barssince, ta.valuewhen, ta.pivothigh, ta.pivotlow, ta.linreg, ta.correlation, ta.percentrank, ta.median, ta.range, ta.sar, ta.tsi | The same names and arguments, except ta.sar, which is ta.psar(start, increment, maximum), and ta.obv, which is the call ta.obv() |
| [line, signal, hist] = ta.macd(close, 12, 26, 9) | ta.macd_line(close, 12, 26), ta.macd_signal(close, 12, 26, 9), ta.macd_hist(close, 12, 26, 9) |
| [middle, upper, lower] = ta.bb(close, 20, 2) | ta.sma(close, 20), ta.bb_upper(close, 20, 2), ta.bb_lower(close, 20, 2) |
| [middle, upper, lower] = ta.kc(close, 20, 2) | ta.ema(close, 20), ta.kc_upper(close, 20, 2), ta.kc_lower(close, 20, 2) |
| [trend, direction] = ta.supertrend(3, 10) | ta.supertrend(3, 10) and ta.supertrend_dir(3, 10). The direction is -1 in an up trend, as in Pine |
| [plus, minus, adx] = ta.dmi(14, 14) | ta.plus_di(14), ta.minus_di(14), ta.adx(14, 14) |
| request.security(syminfo.tickerid, "60", close) | mtf.close(60) for the hour this bar belongs to so far, mtf.prev_close(60) for the last finished hour; the chart instrument only |
| dayofmonth, dayofweek, hour, minute, month, year | time.day(time, "America/New_York") and its siblings, with the zone stated; Pine reads the exchange clock, which for CME futures is "America/Chicago". dayofweek is time.weekday(time, zone) + 1. To read yesterday, store it first: let day: float = time.day(time, "America/Chicago"), then day[1] |
| plot, plotshape, barcolor, fill, hline | plot.line, plot.marker, plot.candle_color, plot.band, plot.hline or plot.panel_hline |
| label.new, line.new, box.new, table.cell | plot.text, plot.segment, plot.box or plot.rect, plot.table |
| color.red, color.new(c, 50), color.rgb(r, g, b, t), color.from_gradient(v, lo, hi, c1, c2) | The same |
| str.tostring, str.length, str.contains, str.upper, str.substring | The same; join text with str.concat, never with + |
| Arrays, matrices, maps, types, methods, libraries, request.*, strategy.* | Not part of the language |
- A window with nan anywhere in it answers nan. Pine skips na inside some windows; XFlow Script does not, so wrap a source that can be absent in nz.
- ta.supertrend and ta.supertrend_dir answer nan while the ATR warms up, where Pine starts with a value.
- ta.rma on its own starts from the first value, where Pine starts from a simple average. ta.rsi, ta.atr and the directional indicators start the Pine way.
- ta.tsi answers a ratio from -1 to 1, as Pine does. Multiply by 100 for a percent scale.
- dayofweek counts Sunday as 1; time.weekday counts Sunday as 0.
- mtf.* buckets are counted from midnight UTC, so mtf.close(1440) is the UTC calendar day, not the futures session. Use session.* for sessions.
- Every typed declaration is checked on every bar. Annotate with float unless the value is always a whole number.
- An unknown Pine name is refused with a line naming the XFlow Script equivalent, for example time.day for dayofmonth.
A port, line by line
//@version=6
indicator("Daily Typical Price", overlay = true)
mult = input.float(1.0, "Band multiplier")
newDay = dayofmonth != dayofmonth[1]
var float total = 0.0
var float count = 0.0
total := newDay ? hlc3 : total + hlc3
count := newDay ? 1 : count + 1
average = total / count
deviation = ta.atr(14) * mult
plot(average, color = close > average ? color.green : color.red, linewidth = 2)
plot(average + deviation, color = color.new(color.gray, 50))
plot(average - deviation, color = color.new(color.gray, 50))//@xfscript 1
indicator("Daily Typical Price")
let mult: float = input.float(1, "mult", "Band multiplier", 0.1, 5, 0.1)
let ny_day: float = time.day(time, "America/New_York")
let new_day: bool = ny_day != ny_day[1]
var total: float = 0
var count: float = 0
total := new_day ? hlc3 : total + hlc3
count := new_day ? 1 : count + 1
let average: float = total / count
let deviation: float = ta.atr(14) * mult
plot.line(average, close > average ? color.green : color.red, 2, "solid")
plot.line(average + deviation, color.new(color.gray, 50), 1, "solid")
plot.line(average - deviation, color.new(color.gray, 50), 1, "solid")dayofmonth became a named series in a stated zone, so day[1] has something to read. The rest is the same line in the same order.
