@hoox-sh/pynets 0.3.0 → 0.5.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 +30 -0
- package/README.md +7 -5
- package/dist/browser.js +66 -66
- package/dist/index.js +2009 -47
- package/package.json +1 -1
- package/src/cli/rich.ts +1 -1
- package/src/runtime/compile/collections.ts +4 -0
- package/src/runtime/compile/draw.ts +609 -19
- package/src/runtime/compile/emit.ts +98 -1
- package/src/runtime/compile/emit_call.ts +366 -10
- package/src/runtime/compile/runtime.ts +71 -1
- package/src/runtime/compile/strategy.ts +253 -1
- package/src/runtime/footprint.ts +272 -0
- package/src/runtime/interpret.ts +325 -8
- package/src/runtime/request.ts +19 -4
- package/src/runtime/ta.ts +392 -0
|
@@ -418,6 +418,8 @@ function emitName(state: State, node: Name): string {
|
|
|
418
418
|
if (CHART_LOCALS.has(id)) return id;
|
|
419
419
|
if (state.ctx.userFuncs.has(id)) return id;
|
|
420
420
|
if (state.ctx.enumTypes.has(id)) return JSON.stringify(id);
|
|
421
|
+
// Dataset last-bar time on every bar (interpret ctx.timenow / lastBarTime).
|
|
422
|
+
if (id === "timenow") return "__h.timenow(time_arr)";
|
|
421
423
|
return safeIdent(id);
|
|
422
424
|
}
|
|
423
425
|
|
|
@@ -540,8 +542,57 @@ const STRATEGY_QUERY_ATTRS = new Set([
|
|
|
540
542
|
"margin_liquidation_price",
|
|
541
543
|
"position_avg_price",
|
|
542
544
|
"initial_capital",
|
|
545
|
+
"cash",
|
|
546
|
+
"position_entry_name",
|
|
547
|
+
"account_currency",
|
|
548
|
+
"default_entry_qty",
|
|
549
|
+
"max_contracts_held_all",
|
|
550
|
+
"max_contracts_held_long",
|
|
551
|
+
"max_contracts_held_short",
|
|
552
|
+
"wintrades",
|
|
553
|
+
"losstrades",
|
|
554
|
+
"eventrades",
|
|
555
|
+
"grossprofit",
|
|
556
|
+
"grossloss",
|
|
557
|
+
"avg_trade",
|
|
558
|
+
"avg_winning_trade",
|
|
559
|
+
"avg_losing_trade",
|
|
560
|
+
"netprofit_percent",
|
|
561
|
+
"openprofit_percent",
|
|
562
|
+
"grossprofit_percent",
|
|
563
|
+
"grossloss_percent",
|
|
564
|
+
"avg_trade_percent",
|
|
565
|
+
"avg_winning_trade_percent",
|
|
566
|
+
"avg_losing_trade_percent",
|
|
567
|
+
"max_drawdown",
|
|
568
|
+
"max_drawdown_percent",
|
|
569
|
+
"max_runup",
|
|
570
|
+
"max_runup_percent",
|
|
571
|
+
"percent_profitable",
|
|
572
|
+
"winrate",
|
|
573
|
+
"profitfactor",
|
|
574
|
+
"profit_factor",
|
|
543
575
|
]);
|
|
544
576
|
|
|
577
|
+
/** Nested `strategy.*` constants (interpret `strategySeriesValue`). */
|
|
578
|
+
const STRATEGY_NESTED_CONSTS: Record<string, string> = {
|
|
579
|
+
"strategy.direction.long": "long",
|
|
580
|
+
"strategy.direction.short": "short",
|
|
581
|
+
"strategy.direction.all": "all",
|
|
582
|
+
"strategy.oca.none": "none",
|
|
583
|
+
"strategy.oca.cancel": "cancel",
|
|
584
|
+
"strategy.oca.reduce": "reduce",
|
|
585
|
+
"strategy.commission.percent": "percent",
|
|
586
|
+
"strategy.commission.cash_per_order": "cash_per_order",
|
|
587
|
+
"strategy.commission.cash_per_contract": "cash_per_contract",
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
/** Nested `strategy.*` series that are not a single identifier. */
|
|
591
|
+
const STRATEGY_NESTED_CALLS: Record<string, string> = {
|
|
592
|
+
"strategy.closedtrades.first_index": "closedtrades_first_index",
|
|
593
|
+
"strategy.opentrades.capital_held": "capital_held",
|
|
594
|
+
};
|
|
595
|
+
|
|
545
596
|
/** Namespaces used as call receivers or dotted constants — not UDT field access. */
|
|
546
597
|
const ATTR_NAMESPACES = new Set([
|
|
547
598
|
"ta",
|
|
@@ -652,6 +703,26 @@ const ATTR_CONSTANTS: Record<string, string | number | boolean> = {
|
|
|
652
703
|
"hline.style_solid": "solid",
|
|
653
704
|
"hline.style_dashed": "dashed",
|
|
654
705
|
"hline.style_dotted": "dotted",
|
|
706
|
+
// Python plotting.py PlotStyle — longer than hline's "solid".
|
|
707
|
+
"plot.linestyle_solid": "linestyle_solid",
|
|
708
|
+
"plot.linestyle_dashed": "linestyle_dashed",
|
|
709
|
+
"plot.linestyle_dotted": "linestyle_dotted",
|
|
710
|
+
// Python plotting.py plot.style_* (dispatch tag 0 strings).
|
|
711
|
+
"plot.style_line": "style_line",
|
|
712
|
+
"plot.style_linebr": "style_linebr",
|
|
713
|
+
"plot.style_stepline": "style_stepline",
|
|
714
|
+
"plot.style_steplinebr": "style_steplinebr",
|
|
715
|
+
"plot.style_stepline_diamond": "style_stepline_diamond",
|
|
716
|
+
"plot.style_histogram": "style_histogram",
|
|
717
|
+
"plot.style_columns": "style_columns",
|
|
718
|
+
"plot.style_cross": "style_cross",
|
|
719
|
+
"plot.style_area": "style_area",
|
|
720
|
+
"plot.style_areabr": "style_areabr",
|
|
721
|
+
"plot.style_circles": "style_circles",
|
|
722
|
+
// Python alerts.py FREQ_* tokens.
|
|
723
|
+
"alert.freq_once_per_bar": "once_per_bar",
|
|
724
|
+
"alert.freq_once_per_bar_close": "once_per_bar_close",
|
|
725
|
+
"alert.freq_all": "all",
|
|
655
726
|
"dayofweek.sunday": 1,
|
|
656
727
|
"dayofweek.monday": 2,
|
|
657
728
|
"dayofweek.tuesday": 3,
|
|
@@ -688,6 +759,8 @@ const ATTR_CONST_NS = new Set([
|
|
|
688
759
|
"display",
|
|
689
760
|
"position",
|
|
690
761
|
"hline",
|
|
762
|
+
"plot",
|
|
763
|
+
"alert",
|
|
691
764
|
"dayofweek",
|
|
692
765
|
"month",
|
|
693
766
|
]);
|
|
@@ -847,13 +920,29 @@ function emitAttribute(state: State, node: Attribute): string {
|
|
|
847
920
|
if (attr === "avg_price_stock") return `"stock"`;
|
|
848
921
|
if (attr === "avg_price_futures") return `"futures"`;
|
|
849
922
|
if (attr === "avg_price_inverse") return `"inverse"`;
|
|
850
|
-
if (attr === "cash") return `"cash"`;
|
|
851
923
|
if (attr === "fixed") return `"fixed"`;
|
|
852
924
|
if (attr === "percent_of_equity") return `"percent_of_equity"`;
|
|
925
|
+
// `strategy.commission` the series is 0; `strategy.commission.percent` is nested.
|
|
926
|
+
if (attr === "commission") return "0";
|
|
853
927
|
if (STRATEGY_QUERY_ATTRS.has(attr)) {
|
|
854
928
|
state.ctx.usesStrategy = true;
|
|
855
929
|
return `__h.strategy.${attr}()`;
|
|
856
930
|
}
|
|
931
|
+
return "null";
|
|
932
|
+
}
|
|
933
|
+
if (node.attr === "all" && node.value.kind === "Name") {
|
|
934
|
+
const kind = node.value.id;
|
|
935
|
+
if (
|
|
936
|
+
kind === "line" ||
|
|
937
|
+
kind === "label" ||
|
|
938
|
+
kind === "box" ||
|
|
939
|
+
kind === "table" ||
|
|
940
|
+
kind === "polyline" ||
|
|
941
|
+
kind === "linefill"
|
|
942
|
+
) {
|
|
943
|
+
state.ctx.usesDrawings = true;
|
|
944
|
+
return `__h.draw.all(${JSON.stringify(kind)})`;
|
|
945
|
+
}
|
|
857
946
|
}
|
|
858
947
|
if (node.value.kind === "Name") {
|
|
859
948
|
const members = state.ctx.enumTypes.get(node.value.id);
|
|
@@ -863,6 +952,14 @@ function emitAttribute(state: State, node: Attribute): string {
|
|
|
863
952
|
}
|
|
864
953
|
const qn = attrQualifiedName(node);
|
|
865
954
|
if (qn != null) {
|
|
955
|
+
const nested = STRATEGY_NESTED_CONSTS[qn];
|
|
956
|
+
if (nested !== undefined) return JSON.stringify(nested);
|
|
957
|
+
const nestedCall = STRATEGY_NESTED_CALLS[qn];
|
|
958
|
+
if (nestedCall != null) {
|
|
959
|
+
state.ctx.usesStrategy = true;
|
|
960
|
+
return `__h.strategy.${nestedCall}()`;
|
|
961
|
+
}
|
|
962
|
+
if (qn.startsWith("strategy.") && qn.split(".").length > 2) return "null";
|
|
866
963
|
const dot = qn.indexOf(".");
|
|
867
964
|
const root = dot < 0 ? qn : qn.slice(0, dot);
|
|
868
965
|
if (ATTR_CONST_NS.has(root)) {
|