@hoox-sh/pynets 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/README.md +6 -4
- package/dist/browser.js +68 -68
- package/dist/index.js +2551 -205
- package/package.json +1 -1
- package/src/cli/rich.ts +1 -1
- package/src/generated/PinescriptLexerBase.ts +22 -4
- package/src/parser/LexerBase.ts +22 -4
- package/src/runtime/compile/draw.ts +26 -2
- package/src/runtime/compile/emit_call.ts +485 -6
- package/src/runtime/compile/helpers.ts +2 -1
- package/src/runtime/compile/runtime.ts +20 -5
- package/src/runtime/compile/strategy.ts +5 -2
- package/src/runtime/interpret.ts +680 -41
- package/src/runtime/str.ts +3 -2
- package/src/runtime/strategy.ts +164 -12
- package/src/runtime/ta.ts +1667 -149
- package/src/runtime/time.ts +12 -0
|
@@ -155,6 +155,62 @@ const TA_METHODS = new Set([
|
|
|
155
155
|
"volume_profile_high",
|
|
156
156
|
"volume_profile_low",
|
|
157
157
|
"volume_thrust",
|
|
158
|
+
"sma_weighted",
|
|
159
|
+
"apo",
|
|
160
|
+
"atr_normalized",
|
|
161
|
+
"beta",
|
|
162
|
+
"r_squared",
|
|
163
|
+
"comovement",
|
|
164
|
+
"skewness",
|
|
165
|
+
"kurtosis",
|
|
166
|
+
"volume_weighted_momentum",
|
|
167
|
+
"parkinson",
|
|
168
|
+
"garman_klass",
|
|
169
|
+
"mean_reversion_score",
|
|
170
|
+
"market_condition",
|
|
171
|
+
"order_flow_imbalance",
|
|
172
|
+
"liquidity_score",
|
|
173
|
+
"fear_greed_index",
|
|
174
|
+
"crowd_sentiment",
|
|
175
|
+
"smart_money_flow",
|
|
176
|
+
"trend_confirmation_score",
|
|
177
|
+
"max_loss_level",
|
|
178
|
+
"profit_lock_level",
|
|
179
|
+
"position_sizing",
|
|
180
|
+
"kelly_criterion",
|
|
181
|
+
"risk_reward_ratio",
|
|
182
|
+
"risk_reward_asymmetry",
|
|
183
|
+
"probability_of_movement",
|
|
184
|
+
"trend_strength",
|
|
185
|
+
"breakeven_level",
|
|
186
|
+
"market_structure_pivot",
|
|
187
|
+
"position_sizing_score",
|
|
188
|
+
"trailing_exit_level",
|
|
189
|
+
"optimal_entry_zone",
|
|
190
|
+
"mean_reversion_entry",
|
|
191
|
+
"multi_timeframe_signal",
|
|
192
|
+
"market_timing_index",
|
|
193
|
+
"regime_adaptive_signal",
|
|
194
|
+
"strategy_score",
|
|
195
|
+
"breakout_detection",
|
|
196
|
+
"ema_cross_signal",
|
|
197
|
+
"momentum_filter",
|
|
198
|
+
"volatility_regime",
|
|
199
|
+
"economic_impact_score",
|
|
200
|
+
"contrarian_signal",
|
|
201
|
+
"drawdown_recovery_level",
|
|
202
|
+
"pivot_point_levels",
|
|
203
|
+
"volatility_regime_score",
|
|
204
|
+
"correlation_filter",
|
|
205
|
+
"advanced_breakout_detector",
|
|
206
|
+
"pullback_bounce_level",
|
|
207
|
+
"divergence_detector",
|
|
208
|
+
"momentum_divergence",
|
|
209
|
+
"spread_analysis",
|
|
210
|
+
"employment_cycle_indicator",
|
|
211
|
+
"gdp_growth_proxy",
|
|
212
|
+
"inflation_proxy_indicator",
|
|
213
|
+
"expected_value",
|
|
158
214
|
]);
|
|
159
215
|
|
|
160
216
|
/**
|
|
@@ -367,6 +423,13 @@ export function emitCall(ctx: EmitCtx, node: Call, visit: VisitFn): string {
|
|
|
367
423
|
ctx.needsHeikinashi = true;
|
|
368
424
|
return `"__HEIKINASHI__"`;
|
|
369
425
|
}
|
|
426
|
+
if (name === "ticker_inherit") {
|
|
427
|
+
const fallback = pick(args, 0, ["ticker", "tickerid", "from", "source"], `"SYMBOL"`);
|
|
428
|
+
return pick(args, 1, ["symbol", "ticker"], fallback);
|
|
429
|
+
}
|
|
430
|
+
if (name === "renko" || name === "kagi" || name === "linebreak" || name === "pointfigure") {
|
|
431
|
+
return pick(args, 0, ["ticker", "tickerid", "symbol"], `"SYMBOL"`);
|
|
432
|
+
}
|
|
370
433
|
// ticker.new / standard / modify / renko / kagi / linebreak / pointfigure → first arg or "SYMBOL"
|
|
371
434
|
if (name.startsWith("ticker_")) {
|
|
372
435
|
return pick(args, 0, ["symbol", "ticker", "tickerid"], `"SYMBOL"`);
|
|
@@ -530,6 +593,26 @@ function hasArg(args: CallArgs, index: number, names: string[]): boolean {
|
|
|
530
593
|
return index >= 0 && index < args.pos.length;
|
|
531
594
|
}
|
|
532
595
|
|
|
596
|
+
/** Bare series names: Python sees a `PineSeries`, so list-only handlers return `na`. */
|
|
597
|
+
const BARE_SERIES_NAMES = new Set([
|
|
598
|
+
"open",
|
|
599
|
+
"high",
|
|
600
|
+
"low",
|
|
601
|
+
"close",
|
|
602
|
+
"volume",
|
|
603
|
+
"hl2",
|
|
604
|
+
"hlc3",
|
|
605
|
+
"ohlc4",
|
|
606
|
+
"hlcc4",
|
|
607
|
+
"time",
|
|
608
|
+
"time_close",
|
|
609
|
+
]);
|
|
610
|
+
|
|
611
|
+
function hasSeriesArg(args: CallArgs): boolean {
|
|
612
|
+
const isSeries = (n: expr): boolean => n.kind === "Name" && BARE_SERIES_NAMES.has(n.id);
|
|
613
|
+
return args.posNodes.some(isSeries) || Object.values(args.kwNodes).some(isSeries);
|
|
614
|
+
}
|
|
615
|
+
|
|
533
616
|
/** True when a keyword argument named one of *names* is present (interpret hasKwarg). */
|
|
534
617
|
function hasAnyKw(args: CallArgs, names: string[]): boolean {
|
|
535
618
|
return names.some((n) => Object.hasOwn(args.kw, n));
|
|
@@ -559,6 +642,11 @@ function cellOf(expr: string): string {
|
|
|
559
642
|
return `((__c) => (__c == null ? null : typeof __c === "boolean" ? (__c ? 1 : 0) : (typeof __c === "number" && Number.isFinite(__c) ? __c : null)))(${expr})`;
|
|
560
643
|
}
|
|
561
644
|
|
|
645
|
+
/** Cell or array/object (history-based TA args keep arrays intact). */
|
|
646
|
+
function arrOrCell(expr: string): string {
|
|
647
|
+
return `((__v) => (__v != null && typeof __v === "object" ? __v : (__v == null ? null : typeof __v === "boolean" ? (__v ? 1 : 0) : (typeof __v === "number" && Number.isFinite(__v) ? __v : null))))(${expr})`;
|
|
648
|
+
}
|
|
649
|
+
|
|
562
650
|
/**
|
|
563
651
|
* Interpret `wave10bList`: a Pine array becomes its cells; a scalar is a
|
|
564
652
|
* one-element list. Bar-mode series stay one element.
|
|
@@ -567,6 +655,11 @@ function cellList(expr: string): string {
|
|
|
567
655
|
return `(() => { const __v = ${expr}; const __cell = (e) => (e == null ? null : typeof e === "boolean" ? (e ? 1 : 0) : (typeof e === "number" && Number.isFinite(e) ? e : null)); if (__v != null && typeof __v.size === "function" && typeof __v.get === "function") { const __n = __v.size(); const __o = []; for (let __i = 0; __i < __n; __i++) __o.push(__cell(__v.get(__i))); return __o; } return [__cell(__v)]; })()`;
|
|
568
656
|
}
|
|
569
657
|
|
|
658
|
+
/** Interpret `seriesLastCell`: array → last cell; scalar → the value itself. */
|
|
659
|
+
function cellLast(expr: string): string {
|
|
660
|
+
return `(() => { const __v = ${expr}; const __cell = (e) => (e == null ? null : typeof e === "boolean" ? (e ? 1 : 0) : (typeof e === "number" && Number.isFinite(e) ? e : null)); if (__v != null && typeof __v.size === "function" && typeof __v.get === "function") { const __n = __v.size(); return __n === 0 ? null : __cell(__v.get(__n - 1)); } return __cell(__v); })()`;
|
|
661
|
+
}
|
|
662
|
+
|
|
570
663
|
const DRAW_KINDS = new Set(["label", "line", "box", "table", "polyline", "linefill"]);
|
|
571
664
|
|
|
572
665
|
const ARRAY_SIGS: Record<string, string[][]> = {
|
|
@@ -953,6 +1046,10 @@ function emitDraw(ctx: EmitCtx, name: string, methodSrc: expr | null, args: Call
|
|
|
953
1046
|
code = `__h.draw.box_new(__bar_idx, ${pick(args, 0, ["left"], "0")}, ${pick(args, 1, ["top"], "0")}, ${pick(args, 2, ["right"], "0")}, ${pick(args, 3, ["bottom"], "0")})`;
|
|
954
1047
|
} else if (kind === "polyline") {
|
|
955
1048
|
code = `__h.draw.polyline_new(__bar_idx, ${pick(args, 0, ["points"], "null")})`;
|
|
1049
|
+
} else if (kind === "table") {
|
|
1050
|
+
// Pine positional order: (position, columns, rows, bgcolor, frame_color,
|
|
1051
|
+
// frame_width, border_color, border_width, force_overlay).
|
|
1052
|
+
code = `__h.draw.table_new(__bar_idx, ${pick(args, 0, ["position"], "null")}, ${pick(args, 1, ["columns"], "null")}, ${pick(args, 2, ["rows"], "null")}, ${pick(args, 3, ["bgcolor"], "null")}, ${pick(args, 4, ["frame_color"], "null")}, ${pick(args, 5, ["frame_width"], "null")}, ${pick(args, 6, ["border_color"], "null")}, ${pick(args, 7, ["border_width"], "null")}, ${pick(args, 8, ["force_overlay"], "null")})`;
|
|
956
1053
|
} else if (kind === "linefill") {
|
|
957
1054
|
const color = hasArg(args, 2, ["color"]) ? pick(args, 2, ["color"], "null") : "null";
|
|
958
1055
|
code = `__h.draw.linefill_new(__bar_idx, ${pick(args, 0, ["id1", "line1"], "null")}, ${pick(args, 1, ["id2", "line2"], "null")}, ${color})`;
|
|
@@ -1619,6 +1716,11 @@ function taCall(method: string, site: string, parts: string[]): string {
|
|
|
1619
1716
|
return `__h.ta.${method}(${site}, ${parts.join(", ")})`;
|
|
1620
1717
|
}
|
|
1621
1718
|
|
|
1719
|
+
/** Call a stateless TaEngine method (no call-site argument). */
|
|
1720
|
+
function taPure(method: string, parts: string[]): string {
|
|
1721
|
+
return `__h.ta.${method}(${parts.join(", ")})`;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1622
1724
|
function emitTa(ctx: EmitCtx, method: string, args: CallArgs): string {
|
|
1623
1725
|
if (!TA_METHODS.has(method)) return "null";
|
|
1624
1726
|
if (method === "ad") method = "accdist";
|
|
@@ -2089,17 +2191,31 @@ function emitTa(ctx: EmitCtx, method: string, args: CallArgs): string {
|
|
|
2089
2191
|
]);
|
|
2090
2192
|
}
|
|
2091
2193
|
if (method === "stoch_smooth") {
|
|
2092
|
-
return
|
|
2194
|
+
return taCall("stochSmooth", site, [
|
|
2195
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2196
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2197
|
+
cellOf(pick(args, 2, ["close"], "null")),
|
|
2198
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2199
|
+
cellOf(pick(args, 4, ["smooth_k", "k"], "null")),
|
|
2200
|
+
cellOf(pick(args, 5, ["smooth_d", "d"], "null")),
|
|
2201
|
+
]);
|
|
2093
2202
|
}
|
|
2094
2203
|
if (method === "engulfing") {
|
|
2095
|
-
//
|
|
2096
|
-
return `(() => { ${cellOf(pick(args, 0, ["open"], "null"))}; ${cellOf(pick(args, 1, ["high"], "null"))}; ${cellOf(pick(args, 2, ["low"], "null"))}; ${cellOf(pick(args, 3, ["close"], "null"))}; return __h.ta.engulfing(); })()`;
|
|
2204
|
+
// Args are still evaluated (interpret reads all four); high/low are unused.
|
|
2205
|
+
return `(() => { const __o = ${cellOf(pick(args, 0, ["open"], "null"))}; ${cellOf(pick(args, 1, ["high"], "null"))}; ${cellOf(pick(args, 2, ["low"], "null"))}; const __c = ${cellOf(pick(args, 3, ["close"], "null"))}; return __h.ta.engulfing(${site}, __o, __c); })()`;
|
|
2097
2206
|
}
|
|
2098
2207
|
if (method === "inside_bar_pattern") {
|
|
2099
|
-
return
|
|
2208
|
+
return taCall("insideBarPattern", site, [
|
|
2209
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2210
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2211
|
+
]);
|
|
2100
2212
|
}
|
|
2101
2213
|
if (method === "double_top_bottom") {
|
|
2102
|
-
return
|
|
2214
|
+
return taCall("doubleTopBottom", site, [
|
|
2215
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2216
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2217
|
+
cellOf(pick(args, 2, ["period", "length"], "null")),
|
|
2218
|
+
]);
|
|
2103
2219
|
}
|
|
2104
2220
|
if (method === "voi") {
|
|
2105
2221
|
return `__h.ta.voi(${cellOf(pick(args, 0, ["buy_volume", "buy"], "null"))}, ${cellOf(pick(args, 1, ["sell_volume", "sell"], "null"))})`;
|
|
@@ -2113,7 +2229,10 @@ function emitTa(ctx: EmitCtx, method: string, args: CallArgs): string {
|
|
|
2113
2229
|
if (method === "rsi_divergence") {
|
|
2114
2230
|
// Missing period is 0 (interpret `period ?? 0`), not the engine's null → na.
|
|
2115
2231
|
const period = `((__n) => (__n == null ? 0 : __n))(${cellOf(pick(args, 1, ["period", "length"], "null"))})`;
|
|
2116
|
-
return
|
|
2232
|
+
return taCall("rsiDivergence", site, [
|
|
2233
|
+
cellLast(pick(args, 0, ["rsi_series", "series", "source"], "null")),
|
|
2234
|
+
period,
|
|
2235
|
+
]);
|
|
2117
2236
|
}
|
|
2118
2237
|
if (method === "cumulative_delta") {
|
|
2119
2238
|
return taCall("cumulativeDelta", site, [
|
|
@@ -2148,5 +2267,365 @@ function emitTa(ctx: EmitCtx, method: string, args: CallArgs): string {
|
|
|
2148
2267
|
`((__n) => (__n == null ? 0.3 : __n))(${sens})`,
|
|
2149
2268
|
]);
|
|
2150
2269
|
}
|
|
2270
|
+
if (method === "sma_weighted") {
|
|
2271
|
+
return taCall("smaWeighted", site, [
|
|
2272
|
+
cellOf(pick(args, 0, ["series", "source"], "null")),
|
|
2273
|
+
cellOf(pick(args, 1, ["period", "length"], "null")),
|
|
2274
|
+
pick(args, 2, ["weight_type", "weight"], '"linear"'),
|
|
2275
|
+
]);
|
|
2276
|
+
}
|
|
2277
|
+
if (method === "apo") {
|
|
2278
|
+
return taCall("apo", site, [
|
|
2279
|
+
cellOf(pick(args, 0, ["series", "source"], "null")),
|
|
2280
|
+
cellOf(pick(args, 1, ["fast_period", "fast"], "null")),
|
|
2281
|
+
cellOf(pick(args, 2, ["slow_period", "slow"], "null")),
|
|
2282
|
+
]);
|
|
2283
|
+
}
|
|
2284
|
+
if (method === "atr_normalized") {
|
|
2285
|
+
return taCall("atrNormalized", site, [
|
|
2286
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2287
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2288
|
+
cellOf(pick(args, 2, ["close"], "null")),
|
|
2289
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2290
|
+
]);
|
|
2291
|
+
}
|
|
2292
|
+
if (method === "beta" || method === "r_squared" || method === "comovement") {
|
|
2293
|
+
const fn = method === "beta" ? "beta" : method === "r_squared" ? "rSquared" : "comovement";
|
|
2294
|
+
return taCall(fn, site, [
|
|
2295
|
+
cellOf(pick(args, 0, ["series1", "series", "source"], "null")),
|
|
2296
|
+
cellOf(pick(args, 1, ["series2", "series_b", "other"], "null")),
|
|
2297
|
+
cellOf(pick(args, 2, ["length", "period"], "null")),
|
|
2298
|
+
]);
|
|
2299
|
+
}
|
|
2300
|
+
if (method === "skewness" || method === "kurtosis") {
|
|
2301
|
+
return taCall(method, site, [
|
|
2302
|
+
cellOf(pick(args, 0, ["series", "source"], "null")),
|
|
2303
|
+
cellOf(pick(args, 1, ["period", "length"], "null")),
|
|
2304
|
+
]);
|
|
2305
|
+
}
|
|
2306
|
+
if (method === "volume_weighted_momentum") {
|
|
2307
|
+
return taCall("volumeWeightedMomentum", site, [
|
|
2308
|
+
cellOf(pick(args, 0, ["series", "source"], "null")),
|
|
2309
|
+
cellOf(pick(args, 1, ["volume"], "null")),
|
|
2310
|
+
cellOf(pick(args, 2, ["length", "period"], "null")),
|
|
2311
|
+
]);
|
|
2312
|
+
}
|
|
2313
|
+
if (method === "parkinson") {
|
|
2314
|
+
if (hasSeriesArg(args)) return "null";
|
|
2315
|
+
return `__h.ta.parkinson(${cellOf(pick(args, 0, ["high"], "null"))}, ${cellOf(pick(args, 1, ["low"], "null"))})`;
|
|
2316
|
+
}
|
|
2317
|
+
if (method === "garman_klass") {
|
|
2318
|
+
if (hasSeriesArg(args)) return "null";
|
|
2319
|
+
return `__h.ta.garmanKlass(${cellOf(pick(args, 0, ["high"], "null"))}, ${cellOf(pick(args, 1, ["low"], "null"))}, ${cellOf(pick(args, 2, ["close"], "null"))}, ${cellOf(pick(args, 3, ["open"], "null"))})`;
|
|
2320
|
+
}
|
|
2321
|
+
if (method === "mean_reversion_score") {
|
|
2322
|
+
return taCall("meanReversionScore", site, [
|
|
2323
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
2324
|
+
cellOf(pick(args, 1, ["sma"], "null")),
|
|
2325
|
+
cellOf(pick(args, 2, ["stdev", "std_dev"], "null")),
|
|
2326
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2327
|
+
]);
|
|
2328
|
+
}
|
|
2329
|
+
if (method === "market_condition") {
|
|
2330
|
+
return taCall("marketCondition", site, [
|
|
2331
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
2332
|
+
cellOf(pick(args, 1, ["atr"], "null")),
|
|
2333
|
+
cellOf(pick(args, 2, ["sma_period", "sma_length"], "null")),
|
|
2334
|
+
cellOf(pick(args, 3, ["stdev_period", "stdev_length"], "null")),
|
|
2335
|
+
]);
|
|
2336
|
+
}
|
|
2337
|
+
if (method === "order_flow_imbalance") {
|
|
2338
|
+
return taCall("orderFlowImbalance", site, [
|
|
2339
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2340
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2341
|
+
cellOf(pick(args, 2, ["close"], "null")),
|
|
2342
|
+
cellOf(pick(args, 3, ["volume"], "null")),
|
|
2343
|
+
cellOf(pick(args, 4, ["period", "length"], "null")),
|
|
2344
|
+
]);
|
|
2345
|
+
}
|
|
2346
|
+
if (method === "liquidity_score") {
|
|
2347
|
+
return taCall("liquidityScore", site, [
|
|
2348
|
+
cellOf(pick(args, 0, ["volume"], "null")),
|
|
2349
|
+
cellOf(pick(args, 1, ["volatility"], "null")),
|
|
2350
|
+
cellOf(pick(args, 2, ["spread"], "null")),
|
|
2351
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2352
|
+
]);
|
|
2353
|
+
}
|
|
2354
|
+
if (method === "fear_greed_index") {
|
|
2355
|
+
return `__h.ta.fearGreedIndex(${cellOf(pick(args, 0, ["rsi"], "null"))}, ${cellOf(pick(args, 1, ["vix"], "null"))}, ${cellOf(pick(args, 2, ["put_call", "put_call_ratio"], "null"))}, ${cellOf(pick(args, 3, ["breadth"], "null"))})`;
|
|
2356
|
+
}
|
|
2357
|
+
if (method === "crowd_sentiment") {
|
|
2358
|
+
return `__h.ta.crowdSentiment(${cellOf(pick(args, 0, ["price_agreement", "price"], "null"))}, ${cellOf(pick(args, 1, ["volume_agreement", "volume"], "null"))}, ${cellOf(pick(args, 2, ["time_agreement", "time"], "null"))})`;
|
|
2359
|
+
}
|
|
2360
|
+
if (method === "smart_money_flow") {
|
|
2361
|
+
return `__h.ta.smartMoneyFlow(${cellOf(pick(args, 0, ["price_change"], "null"))}, ${cellOf(pick(args, 1, ["volume"], "null"))}, ${cellOf(pick(args, 2, ["time_since_high", "time_high"], "null"))}, ${cellOf(pick(args, 3, ["time_since_low", "time_low"], "null"))})`;
|
|
2362
|
+
}
|
|
2363
|
+
if (method === "trend_confirmation_score") {
|
|
2364
|
+
return `__h.ta.trendConfirmationScore(${cellOf(pick(args, 0, ["momentum"], "null"))}, ${cellOf(pick(args, 1, ["trend_alignment"], "null"))}, ${cellOf(pick(args, 2, ["strength"], "null"))}, ${cellOf(pick(args, 3, ["rsi"], "null"))}, ${cellOf(pick(args, 4, ["rsi_alignment"], "null"))})`;
|
|
2365
|
+
}
|
|
2366
|
+
if (method === "max_loss_level") {
|
|
2367
|
+
return `__h.ta.maxLossLevel(${cellOf(pick(args, 0, ["entry", "entry_price"], "null"))}, ${cellOf(pick(args, 1, ["account", "account_size"], "null"))}, ${cellOf(pick(args, 2, ["max_loss_pct", "max_loss_percent"], "null"))})`;
|
|
2368
|
+
}
|
|
2369
|
+
if (method === "profit_lock_level") {
|
|
2370
|
+
return `__h.ta.profitLockLevel(${cellOf(pick(args, 0, ["entry", "entry_price"], "null"))}, ${cellOf(pick(args, 1, ["current", "current_price"], "null"))}, ${cellOf(pick(args, 2, ["trail_pct", "trail_percent"], "null"))}, ${cellOf(pick(args, 3, ["direction"], "null"))})`;
|
|
2371
|
+
}
|
|
2372
|
+
if (method === "position_sizing") {
|
|
2373
|
+
return taPure("positionSizing", [
|
|
2374
|
+
cellOf(pick(args, 0, ["account", "account_size"], "null")),
|
|
2375
|
+
cellOf(pick(args, 1, ["risk_pct", "risk_percent"], "null")),
|
|
2376
|
+
cellOf(pick(args, 2, ["entry", "entry_price"], "null")),
|
|
2377
|
+
cellOf(pick(args, 3, ["stop", "stop_price"], "null")),
|
|
2378
|
+
]);
|
|
2379
|
+
}
|
|
2380
|
+
if (method === "kelly_criterion") {
|
|
2381
|
+
return taPure("kellyCriterion", [
|
|
2382
|
+
cellOf(pick(args, 0, ["win_rate"], "null")),
|
|
2383
|
+
cellOf(pick(args, 1, ["avg_win"], "null")),
|
|
2384
|
+
cellOf(pick(args, 2, ["avg_loss"], "null")),
|
|
2385
|
+
]);
|
|
2386
|
+
}
|
|
2387
|
+
if (method === "risk_reward_ratio") {
|
|
2388
|
+
return taPure("riskRewardRatio", [
|
|
2389
|
+
cellOf(pick(args, 0, ["entry", "entry_price"], "null")),
|
|
2390
|
+
cellOf(pick(args, 1, ["stop", "stop_price"], "null")),
|
|
2391
|
+
cellOf(pick(args, 2, ["target", "target_price"], "null")),
|
|
2392
|
+
]);
|
|
2393
|
+
}
|
|
2394
|
+
if (method === "risk_reward_asymmetry") {
|
|
2395
|
+
return taPure("riskRewardAsymmetry", [
|
|
2396
|
+
cellOf(pick(args, 0, ["entry", "entry_price"], "null")),
|
|
2397
|
+
cellOf(pick(args, 1, ["stop", "stop_price"], "null")),
|
|
2398
|
+
cellOf(pick(args, 2, ["target", "target_price"], "null")),
|
|
2399
|
+
cellOf(pick(args, 3, ["win_rate"], "null")),
|
|
2400
|
+
]);
|
|
2401
|
+
}
|
|
2402
|
+
if (method === "probability_of_movement") {
|
|
2403
|
+
return taPure("probabilityOfMovement", [
|
|
2404
|
+
cellOf(pick(args, 0, ["current", "current_price"], "null")),
|
|
2405
|
+
cellOf(pick(args, 1, ["target", "target_price"], "null")),
|
|
2406
|
+
cellOf(pick(args, 2, ["atr"], "null")),
|
|
2407
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2408
|
+
]);
|
|
2409
|
+
}
|
|
2410
|
+
if (method === "trend_strength") {
|
|
2411
|
+
return taPure("trendStrength", [
|
|
2412
|
+
cellOf(pick(args, 0, ["price", "source"], "null")),
|
|
2413
|
+
cellOf(pick(args, 1, ["adx"], "null")),
|
|
2414
|
+
cellOf(pick(args, 2, ["rsi"], "null")),
|
|
2415
|
+
]);
|
|
2416
|
+
}
|
|
2417
|
+
if (method === "breakeven_level") {
|
|
2418
|
+
return taPure("breakevenLevel", [
|
|
2419
|
+
cellOf(pick(args, 0, ["entry", "entry_price"], "null")),
|
|
2420
|
+
cellOf(pick(args, 1, ["quantity", "qty"], "null")),
|
|
2421
|
+
cellOf(pick(args, 2, ["commission"], "null")),
|
|
2422
|
+
cellOf(pick(args, 3, ["slippage"], "null")),
|
|
2423
|
+
cellOf(pick(args, 4, ["direction"], "null")),
|
|
2424
|
+
]);
|
|
2425
|
+
}
|
|
2426
|
+
if (method === "market_structure_pivot") {
|
|
2427
|
+
return taCall("marketStructurePivot", site, [
|
|
2428
|
+
arrOrCell(pick(args, 0, ["high_list", "high"], "null")),
|
|
2429
|
+
arrOrCell(pick(args, 1, ["low_list", "low"], "null")),
|
|
2430
|
+
cellOf(pick(args, 3, ["period", "left", "left_bars"], "null")),
|
|
2431
|
+
cellOf(pick(args, 4, ["mode", "right", "right_bars"], "null")),
|
|
2432
|
+
]);
|
|
2433
|
+
}
|
|
2434
|
+
if (method === "position_sizing_score") {
|
|
2435
|
+
return taPure("positionSizingScore", [
|
|
2436
|
+
cellOf(pick(args, 0, ["account_risk", "risk"], "null")),
|
|
2437
|
+
cellOf(pick(args, 1, ["volatility"], "null")),
|
|
2438
|
+
cellOf(pick(args, 2, ["conviction"], "null")),
|
|
2439
|
+
cellOf(pick(args, 3, ["correlation"], "null")),
|
|
2440
|
+
]);
|
|
2441
|
+
}
|
|
2442
|
+
if (method === "trailing_exit_level") {
|
|
2443
|
+
return taPure("trailingExitLevel", [
|
|
2444
|
+
cellOf(pick(args, 0, ["entry", "entry_price"], "null")),
|
|
2445
|
+
cellOf(pick(args, 1, ["current", "current_price"], "null")),
|
|
2446
|
+
cellOf(pick(args, 2, ["atr"], "null")),
|
|
2447
|
+
cellOf(pick(args, 3, ["multiplier", "mult"], "null")),
|
|
2448
|
+
cellOf(pick(args, 4, ["step"], "null")),
|
|
2449
|
+
]);
|
|
2450
|
+
}
|
|
2451
|
+
if (method === "optimal_entry_zone") {
|
|
2452
|
+
return taCall("optimalEntryZone", site, [arrOrCell(pick(args, 2, ["close"], "null"))]);
|
|
2453
|
+
}
|
|
2454
|
+
if (method === "mean_reversion_entry") {
|
|
2455
|
+
return taCall("meanReversionEntry", site, [
|
|
2456
|
+
arrOrCell(pick(args, 0, ["price", "source"], "null")),
|
|
2457
|
+
arrOrCell(pick(args, 1, ["sma"], "null")),
|
|
2458
|
+
arrOrCell(pick(args, 2, ["stdev", "std_dev"], "null")),
|
|
2459
|
+
cellOf(pick(args, 4, ["threshold"], "null")),
|
|
2460
|
+
]);
|
|
2461
|
+
}
|
|
2462
|
+
if (method === "multi_timeframe_signal") {
|
|
2463
|
+
return taPure("multiTimeframeSignal", [
|
|
2464
|
+
cellOf(pick(args, 0, ["s1", "signal1"], "null")),
|
|
2465
|
+
cellOf(pick(args, 1, ["s2", "signal2"], "null")),
|
|
2466
|
+
cellOf(pick(args, 2, ["s3", "signal3"], "null")),
|
|
2467
|
+
cellOf(pick(args, 3, ["w1", "weight1"], "null")),
|
|
2468
|
+
cellOf(pick(args, 4, ["w2", "weight2"], "null")),
|
|
2469
|
+
cellOf(pick(args, 5, ["w3", "weight3"], "null")),
|
|
2470
|
+
]);
|
|
2471
|
+
}
|
|
2472
|
+
if (method === "market_timing_index") {
|
|
2473
|
+
return taPure("marketTimingIndex", [
|
|
2474
|
+
cellOf(pick(args, 0, ["trend"], "null")),
|
|
2475
|
+
cellOf(pick(args, 1, ["momentum"], "null")),
|
|
2476
|
+
cellOf(pick(args, 2, ["volatility"], "null")),
|
|
2477
|
+
cellOf(pick(args, 3, ["sentiment"], "null")),
|
|
2478
|
+
]);
|
|
2479
|
+
}
|
|
2480
|
+
if (method === "regime_adaptive_signal") {
|
|
2481
|
+
return taPure("regimeAdaptiveSignal", [
|
|
2482
|
+
cellOf(pick(args, 0, ["signal_strength", "strength"], "null")),
|
|
2483
|
+
pick(args, 1, ["volatility_regime", "vol_regime"], '""'),
|
|
2484
|
+
pick(args, 2, ["trend_regime"], '""'),
|
|
2485
|
+
]);
|
|
2486
|
+
}
|
|
2487
|
+
if (method === "strategy_score") {
|
|
2488
|
+
return taPure("strategyScore", [
|
|
2489
|
+
cellOf(pick(args, 0, ["rsi"], "null")),
|
|
2490
|
+
cellOf(pick(args, 1, ["macd"], "null")),
|
|
2491
|
+
cellOf(pick(args, 2, ["ema_cross"], "null")),
|
|
2492
|
+
cellOf(pick(args, 3, ["trend"], "null")),
|
|
2493
|
+
]);
|
|
2494
|
+
}
|
|
2495
|
+
if (method === "breakout_detection") {
|
|
2496
|
+
return taPure("breakoutDetection", [
|
|
2497
|
+
cellOf(pick(args, 0, ["close", "source"], "null")),
|
|
2498
|
+
cellOf(pick(args, 1, ["resistance"], "null")),
|
|
2499
|
+
cellOf(pick(args, 2, ["support"], "null")),
|
|
2500
|
+
]);
|
|
2501
|
+
}
|
|
2502
|
+
if (method === "ema_cross_signal") {
|
|
2503
|
+
return taCall("emaCrossSignal", site, [
|
|
2504
|
+
cellOf(pick(args, 0, ["fast_ema", "fast"], "null")),
|
|
2505
|
+
cellOf(pick(args, 1, ["slow_ema", "slow"], "null")),
|
|
2506
|
+
cellOf(pick(args, 2, ["threshold"], "null")),
|
|
2507
|
+
]);
|
|
2508
|
+
}
|
|
2509
|
+
if (method === "momentum_filter") {
|
|
2510
|
+
return taCall("momentumFilter", site, [
|
|
2511
|
+
cellOf(pick(args, 0, ["momentum_raw", "momentum"], "null")),
|
|
2512
|
+
cellOf(pick(args, 1, ["volume"], "null")),
|
|
2513
|
+
cellOf(pick(args, 2, ["period", "length"], "null")),
|
|
2514
|
+
]);
|
|
2515
|
+
}
|
|
2516
|
+
if (method === "volatility_regime") {
|
|
2517
|
+
return taCall("volatilityRegime", site, [
|
|
2518
|
+
cellOf(pick(args, 0, ["atr_series", "atr", "source"], "null")),
|
|
2519
|
+
cellOf(pick(args, 1, ["period", "length"], "null")),
|
|
2520
|
+
]);
|
|
2521
|
+
}
|
|
2522
|
+
if (method === "economic_impact_score") {
|
|
2523
|
+
return taPure("economicImpactScore", [
|
|
2524
|
+
cellOf(pick(args, 0, ["price_change"], "null")),
|
|
2525
|
+
cellOf(pick(args, 1, ["volatility"], "null")),
|
|
2526
|
+
cellOf(pick(args, 2, ["volume_change"], "null")),
|
|
2527
|
+
]);
|
|
2528
|
+
}
|
|
2529
|
+
if (method === "contrarian_signal") {
|
|
2530
|
+
return taPure("contrarianSignal", [
|
|
2531
|
+
cellOf(pick(args, 0, ["sentiment"], "null")),
|
|
2532
|
+
cellOf(pick(args, 1, ["volatility"], "null")),
|
|
2533
|
+
cellOf(pick(args, 2, ["time_since_extreme", "time_extreme"], "null")),
|
|
2534
|
+
]);
|
|
2535
|
+
}
|
|
2536
|
+
if (method === "drawdown_recovery_level") {
|
|
2537
|
+
return taPure("drawdownRecoveryLevel", [
|
|
2538
|
+
cellOf(pick(args, 0, ["peak"], "null")),
|
|
2539
|
+
cellOf(pick(args, 1, ["current", "current_price"], "null")),
|
|
2540
|
+
cellOf(pick(args, 2, ["recovery_factor", "factor"], "null")),
|
|
2541
|
+
cellOf(pick(args, 3, ["period", "length"], "null")),
|
|
2542
|
+
]);
|
|
2543
|
+
}
|
|
2544
|
+
if (method === "pivot_point_levels") {
|
|
2545
|
+
return taPure("pivotPointLevels", [
|
|
2546
|
+
cellOf(pick(args, 0, ["high"], "null")),
|
|
2547
|
+
cellOf(pick(args, 1, ["low"], "null")),
|
|
2548
|
+
cellOf(pick(args, 2, ["close"], "null")),
|
|
2549
|
+
pick(args, 3, ["traditional"], "true"),
|
|
2550
|
+
]);
|
|
2551
|
+
}
|
|
2552
|
+
if (method === "volatility_regime_score") {
|
|
2553
|
+
return taCall("volatilityRegimeScore", site, [
|
|
2554
|
+
arrOrCell(pick(args, 0, ["atr_list", "atr"], "null")),
|
|
2555
|
+
arrOrCell(pick(args, 1, ["volatility_list", "volatility"], "null")),
|
|
2556
|
+
arrOrCell(pick(args, 2, ["vix_list", "vix"], "null")),
|
|
2557
|
+
cellOf(pick(args, 3, ["threshold"], "null")),
|
|
2558
|
+
]);
|
|
2559
|
+
}
|
|
2560
|
+
if (method === "correlation_filter") {
|
|
2561
|
+
return taCall("correlationFilter", site, [
|
|
2562
|
+
arrOrCell(pick(args, 0, ["signal1_list", "signal1", "s1"], "null")),
|
|
2563
|
+
arrOrCell(pick(args, 1, ["signal2_list", "signal2", "s2"], "null")),
|
|
2564
|
+
arrOrCell(pick(args, 2, ["signal3_list", "signal3", "s3"], "null")),
|
|
2565
|
+
cellOf(pick(args, 4, ["threshold"], "null")),
|
|
2566
|
+
]);
|
|
2567
|
+
}
|
|
2568
|
+
if (method === "advanced_breakout_detector") {
|
|
2569
|
+
return taCall("advancedBreakoutDetector", site, [
|
|
2570
|
+
arrOrCell(pick(args, 0, ["price_list", "price"], "null")),
|
|
2571
|
+
arrOrCell(pick(args, 1, ["volume_list", "volume"], "null")),
|
|
2572
|
+
cellOf(pick(args, 2, ["level"], "null")),
|
|
2573
|
+
cellOf(pick(args, 3, ["lookback"], "null")),
|
|
2574
|
+
cellOf(pick(args, 4, ["volume_multiplier", "vol_mult"], "null")),
|
|
2575
|
+
]);
|
|
2576
|
+
}
|
|
2577
|
+
if (method === "pullback_bounce_level") {
|
|
2578
|
+
return taCall("pullbackBounceLevel", site, [
|
|
2579
|
+
arrOrCell(pick(args, 0, ["high_list", "high"], "null")),
|
|
2580
|
+
arrOrCell(pick(args, 1, ["low_list", "low"], "null")),
|
|
2581
|
+
cellOf(pick(args, 3, ["trend_direction", "trend_dir"], "null")),
|
|
2582
|
+
cellOf(pick(args, 4, ["lookback"], "null")),
|
|
2583
|
+
]);
|
|
2584
|
+
}
|
|
2585
|
+
if (method === "divergence_detector") {
|
|
2586
|
+
return taCall("divergenceDetector", site, [
|
|
2587
|
+
arrOrCell(pick(args, 0, ["price_list", "price"], "null")),
|
|
2588
|
+
arrOrCell(pick(args, 1, ["indicator_list", "indicator"], "null")),
|
|
2589
|
+
cellOf(pick(args, 2, ["lookback"], "null")),
|
|
2590
|
+
]);
|
|
2591
|
+
}
|
|
2592
|
+
if (method === "momentum_divergence") {
|
|
2593
|
+
return taCall("momentumDivergence", site, [
|
|
2594
|
+
arrOrCell(pick(args, 0, ["price"], "null")),
|
|
2595
|
+
arrOrCell(pick(args, 1, ["momentum_fast", "mom_fast"], "null")),
|
|
2596
|
+
arrOrCell(pick(args, 2, ["momentum_slow", "mom_slow"], "null")),
|
|
2597
|
+
]);
|
|
2598
|
+
}
|
|
2599
|
+
if (method === "spread_analysis") {
|
|
2600
|
+
return taCall("spreadAnalysis", site, [
|
|
2601
|
+
arrOrCell(pick(args, 0, ["bid"], "null")),
|
|
2602
|
+
arrOrCell(pick(args, 1, ["ask"], "null")),
|
|
2603
|
+
cellOf(pick(args, 2, ["period", "length"], "null")),
|
|
2604
|
+
]);
|
|
2605
|
+
}
|
|
2606
|
+
if (method === "employment_cycle_indicator") {
|
|
2607
|
+
return taCall("employmentCycleIndicator", site, [
|
|
2608
|
+
arrOrCell(pick(args, 0, ["cyclical_stocks", "cyclical"], "null")),
|
|
2609
|
+
arrOrCell(pick(args, 1, ["defensive_stocks", "defensive"], "null")),
|
|
2610
|
+
arrOrCell(pick(args, 2, ["unemployment_proxy", "unemployment"], "null")),
|
|
2611
|
+
]);
|
|
2612
|
+
}
|
|
2613
|
+
if (method === "gdp_growth_proxy") {
|
|
2614
|
+
return taCall("gdpGrowthProxy", site, [
|
|
2615
|
+
arrOrCell(pick(args, 0, ["market_breadth", "breadth"], "null")),
|
|
2616
|
+
arrOrCell(pick(args, 1, ["market_volume", "volume"], "null")),
|
|
2617
|
+
arrOrCell(pick(args, 2, ["price_momentum", "momentum"], "null")),
|
|
2618
|
+
]);
|
|
2619
|
+
}
|
|
2620
|
+
if (method === "inflation_proxy_indicator") {
|
|
2621
|
+
return taCall("inflationProxyIndicator", site, [
|
|
2622
|
+
arrOrCell(pick(args, 0, ["usd_index", "usd"], "null")),
|
|
2623
|
+
arrOrCell(pick(args, 1, ["commodity_prices", "commodities"], "null")),
|
|
2624
|
+
arrOrCell(pick(args, 2, ["bond_yields", "yields"], "null")),
|
|
2625
|
+
]);
|
|
2626
|
+
}
|
|
2627
|
+
if (method === "expected_value") {
|
|
2628
|
+
return `__h.ta.expectedValue(${cellList(pick(args, 0, ["returns"], "null"))}, ${cellList(pick(args, 1, ["probabilities", "probs"], "null"))})`;
|
|
2629
|
+
}
|
|
2151
2630
|
return "null";
|
|
2152
2631
|
}
|
|
@@ -20,9 +20,10 @@ export function naNum(v: unknown): number | null {
|
|
|
20
20
|
return NA;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/** Store cell or object handle. Objects (array/map/matrix/UDT) stay intact. */
|
|
23
|
+
/** Store cell or object handle. Objects (array/map/matrix/UDT) and strings stay intact. */
|
|
24
24
|
export function hold(v: unknown): unknown {
|
|
25
25
|
if (v != null && typeof v === "object") return v;
|
|
26
|
+
if (typeof v === "string") return v;
|
|
26
27
|
return naNum(v);
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
} from "../footprint.ts";
|
|
80
80
|
import { resolveCurrencyRate, resolveSeed } from "../request.ts";
|
|
81
81
|
import { TaEngine } from "../ta.ts";
|
|
82
|
-
import { utcPartsFromMs, timestamp, weekOfYear, timeTradingDay, type UtcParts } from "../time.ts";
|
|
82
|
+
import { utcPartsFromMs, timestamp, timestampToMs, weekOfYear, timeTradingDay, type UtcParts } from "../time.ts";
|
|
83
83
|
import { TickerId } from "../ticker.ts";
|
|
84
84
|
import { timeframeInSeconds, timeframePeriodChanged } from "../timeframe.ts";
|
|
85
85
|
import { compileArray, compileMap, compileMatrix } from "./collections.ts";
|
|
@@ -203,8 +203,8 @@ export function createCompileHelpers(opts?: CompileHelperOpts) {
|
|
|
203
203
|
second: calendarSecond,
|
|
204
204
|
dayofweek: calendarDayofweek,
|
|
205
205
|
timestamp,
|
|
206
|
-
weekOfYear,
|
|
207
|
-
timeTradingDay,
|
|
206
|
+
weekOfYear: calendarWeekOfYear,
|
|
207
|
+
timeTradingDay: calendarTimeTradingDay,
|
|
208
208
|
timeframeInSeconds: timeframeInSecondsOrDaily,
|
|
209
209
|
timeframeChange,
|
|
210
210
|
timeClose,
|
|
@@ -339,10 +339,25 @@ function NA_FN(v?: unknown): number | null {
|
|
|
339
339
|
return isNaCell(v) ? 1 : 0;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
/** Unix-ms → UTC calendar part. na / non-finite time → null. */
|
|
342
|
+
/** Unix-ms → UTC calendar part. na / non-finite time → null. Unix-second stamps become ms (Python `utility._timestamp_to_ms`). */
|
|
343
343
|
function utcPart(t: unknown, key: keyof UtcParts): number | null {
|
|
344
344
|
if (typeof t !== "number" || !Number.isFinite(t)) return null;
|
|
345
|
-
|
|
345
|
+
const ms = timestampToMs(t);
|
|
346
|
+
return ms == null ? null : utcPartsFromMs(ms)[key];
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** `weekofyear(t)` with unix-seconds coercion (Python `_resolve_timestamp_arg`). */
|
|
350
|
+
function calendarWeekOfYear(t: unknown): number | null {
|
|
351
|
+
if (typeof t !== "number" || !Number.isFinite(t)) return null;
|
|
352
|
+
const ms = timestampToMs(t);
|
|
353
|
+
return ms == null ? null : weekOfYear(ms);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** `time_tradingday(t)` with unix-seconds coercion (Python `_resolve_timestamp_arg`). */
|
|
357
|
+
function calendarTimeTradingDay(t: unknown): number | null {
|
|
358
|
+
if (typeof t !== "number" || !Number.isFinite(t)) return null;
|
|
359
|
+
const ms = timestampToMs(t);
|
|
360
|
+
return ms == null ? null : timeTradingDay(ms);
|
|
346
361
|
}
|
|
347
362
|
|
|
348
363
|
function calendarYear(t: unknown): number | null {
|
|
@@ -124,6 +124,7 @@ export class CompileStrategy {
|
|
|
124
124
|
high: num(high, this.mark),
|
|
125
125
|
low: num(low, this.mark),
|
|
126
126
|
close: this.mark,
|
|
127
|
+
time: this.time,
|
|
127
128
|
};
|
|
128
129
|
this.ohlc = ohlc;
|
|
129
130
|
this.book.processPending(this.bar, ohlc);
|
|
@@ -141,18 +142,19 @@ export class CompileStrategy {
|
|
|
141
142
|
comment: opts?.comment,
|
|
142
143
|
oca_name: opts?.oca_name,
|
|
143
144
|
oca_type: opts?.oca_type,
|
|
145
|
+
deferMarket: true,
|
|
144
146
|
});
|
|
145
147
|
}
|
|
146
148
|
|
|
147
149
|
close(id?: unknown, qty?: unknown): void {
|
|
148
|
-
this.book.
|
|
150
|
+
this.book.placeClose(this.bar, str(id, ""), this.mark, {
|
|
149
151
|
time: this.time,
|
|
150
152
|
qty: optNum(qty),
|
|
151
153
|
});
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
close_all(_comment?: unknown): void {
|
|
155
|
-
this.book.
|
|
157
|
+
this.book.placeCloseAll(this.bar, this.mark);
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
order(id?: unknown, direction?: unknown, qty?: unknown, opts?: PlaceEntryOpts): void {
|
|
@@ -174,6 +176,7 @@ export class CompileStrategy {
|
|
|
174
176
|
price: this.mark,
|
|
175
177
|
time: this.time,
|
|
176
178
|
ohlc: this.ohlc,
|
|
179
|
+
deferMarket: true,
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
182
|
|