opencode-pyneruntime 6.6.4__py3-none-any.whl

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.
Files changed (261) hide show
  1. opencode_pyneruntime-6.6.4.dist-info/METADATA +281 -0
  2. opencode_pyneruntime-6.6.4.dist-info/RECORD +261 -0
  3. opencode_pyneruntime-6.6.4.dist-info/WHEEL +5 -0
  4. opencode_pyneruntime-6.6.4.dist-info/entry_points.txt +6 -0
  5. opencode_pyneruntime-6.6.4.dist-info/licenses/LICENSE +201 -0
  6. opencode_pyneruntime-6.6.4.dist-info/licenses/NOTICE +21 -0
  7. opencode_pyneruntime-6.6.4.dist-info/top_level.txt +1 -0
  8. pynecore/__init__.py +6 -0
  9. pynecore/cli/__init__.py +2 -0
  10. pynecore/cli/app.py +238 -0
  11. pynecore/cli/commands/__init__.py +343 -0
  12. pynecore/cli/commands/benchmark.py +186 -0
  13. pynecore/cli/commands/compile.py +198 -0
  14. pynecore/cli/commands/data.py +857 -0
  15. pynecore/cli/commands/debug.py +63 -0
  16. pynecore/cli/commands/optimize.py +956 -0
  17. pynecore/cli/commands/plugin.py +242 -0
  18. pynecore/cli/commands/run.py +2006 -0
  19. pynecore/cli/pluggable.py +132 -0
  20. pynecore/cli/utils/__init__.py +0 -0
  21. pynecore/cli/utils/api_error_handler.py +168 -0
  22. pynecore/cli/utils/broker_picker.py +330 -0
  23. pynecore/cli/utils/error_hook.py +28 -0
  24. pynecore/cli/utils/keyreader.py +178 -0
  25. pynecore/cli/utils/provider_picker.py +19 -0
  26. pynecore/cli/utils/symbol_browser.py +1149 -0
  27. pynecore/core/__init__.py +0 -0
  28. pynecore/core/aggregator.py +257 -0
  29. pynecore/core/bar_magnifier.py +168 -0
  30. pynecore/core/broker/__init__.py +64 -0
  31. pynecore/core/broker/defaults.py +113 -0
  32. pynecore/core/broker/disappearance.py +927 -0
  33. pynecore/core/broker/emulator.py +345 -0
  34. pynecore/core/broker/exceptions.py +346 -0
  35. pynecore/core/broker/idempotency.py +401 -0
  36. pynecore/core/broker/intent_builder.py +334 -0
  37. pynecore/core/broker/journal.py +1785 -0
  38. pynecore/core/broker/models.py +1600 -0
  39. pynecore/core/broker/native_failsafe_manager.py +1436 -0
  40. pynecore/core/broker/one_way_emulator.py +1128 -0
  41. pynecore/core/broker/position.py +787 -0
  42. pynecore/core/broker/run_identity.py +126 -0
  43. pynecore/core/broker/software_entry_stop_engine.py +351 -0
  44. pynecore/core/broker/software_partial_bracket_engine.py +1379 -0
  45. pynecore/core/broker/spot_inventory.py +1327 -0
  46. pynecore/core/broker/storage.py +2655 -0
  47. pynecore/core/broker/store_helpers.py +2161 -0
  48. pynecore/core/broker/sync_engine.py +16070 -0
  49. pynecore/core/broker/validation.py +382 -0
  50. pynecore/core/class_property.py +7 -0
  51. pynecore/core/config.py +392 -0
  52. pynecore/core/csv_file.py +547 -0
  53. pynecore/core/currency.py +262 -0
  54. pynecore/core/data_converter.py +1002 -0
  55. pynecore/core/datetime.py +296 -0
  56. pynecore/core/download_info.py +71 -0
  57. pynecore/core/download_runner.py +274 -0
  58. pynecore/core/htf_aggregator.py +181 -0
  59. pynecore/core/import_hook.py +358 -0
  60. pynecore/core/instance_state.py +494 -0
  61. pynecore/core/live_ltf_collector.py +442 -0
  62. pynecore/core/live_ltf_window.py +189 -0
  63. pynecore/core/live_runner.py +1347 -0
  64. pynecore/core/module_property.py +26 -0
  65. pynecore/core/ohlcv_file.py +1888 -0
  66. pynecore/core/overload.py +371 -0
  67. pynecore/core/pine_cast.py +113 -0
  68. pynecore/core/pine_export.py +95 -0
  69. pynecore/core/pine_method.py +244 -0
  70. pynecore/core/pine_range.py +86 -0
  71. pynecore/core/pine_udt.py +69 -0
  72. pynecore/core/plugin/__init__.py +394 -0
  73. pynecore/core/plugin/broker.py +781 -0
  74. pynecore/core/plugin/cli.py +96 -0
  75. pynecore/core/plugin/live_provider.py +208 -0
  76. pynecore/core/plugin/provider.py +331 -0
  77. pynecore/core/provider_string.py +148 -0
  78. pynecore/core/random.py +40 -0
  79. pynecore/core/resampler.py +686 -0
  80. pynecore/core/safe_convert.py +64 -0
  81. pynecore/core/script.py +1011 -0
  82. pynecore/core/script_runner.py +3202 -0
  83. pynecore/core/security.py +1749 -0
  84. pynecore/core/security_process.py +1253 -0
  85. pynecore/core/security_shm.py +456 -0
  86. pynecore/core/series.py +417 -0
  87. pynecore/core/strategy_stats.py +669 -0
  88. pynecore/core/symbol_map.py +134 -0
  89. pynecore/core/syminfo.py +505 -0
  90. pynecore/core/viz.py +591 -0
  91. pynecore/lib/__init__.py +1771 -0
  92. pynecore/lib/_fixnan.py +32 -0
  93. pynecore/lib/_math_stateful.py +202 -0
  94. pynecore/lib/_timeframe_change.py +101 -0
  95. pynecore/lib/adjustment.py +6 -0
  96. pynecore/lib/alert.py +39 -0
  97. pynecore/lib/alert.pyi +14 -0
  98. pynecore/lib/array.py +1051 -0
  99. pynecore/lib/barmerge.py +60 -0
  100. pynecore/lib/barstate.py +30 -0
  101. pynecore/lib/box.py +415 -0
  102. pynecore/lib/chart.py +128 -0
  103. pynecore/lib/color.py +152 -0
  104. pynecore/lib/color.pyi +50 -0
  105. pynecore/lib/currency.py +62 -0
  106. pynecore/lib/dayofweek.py +36 -0
  107. pynecore/lib/dayofweek.pyi +18 -0
  108. pynecore/lib/display.py +8 -0
  109. pynecore/lib/dividends.py +9 -0
  110. pynecore/lib/earnings.py +11 -0
  111. pynecore/lib/extend.py +6 -0
  112. pynecore/lib/font.py +5 -0
  113. pynecore/lib/footprint.py +79 -0
  114. pynecore/lib/format.py +11 -0
  115. pynecore/lib/hline.py +67 -0
  116. pynecore/lib/hline.pyi +24 -0
  117. pynecore/lib/label.py +409 -0
  118. pynecore/lib/line.py +433 -0
  119. pynecore/lib/linefill.py +93 -0
  120. pynecore/lib/location.py +11 -0
  121. pynecore/lib/log.py +362 -0
  122. pynecore/lib/map.py +150 -0
  123. pynecore/lib/math.py +385 -0
  124. pynecore/lib/matrix.py +708 -0
  125. pynecore/lib/order.py +8 -0
  126. pynecore/lib/pivotpointtype.py +8 -0
  127. pynecore/lib/plot.py +95 -0
  128. pynecore/lib/plot.pyi +33 -0
  129. pynecore/lib/polyline.py +91 -0
  130. pynecore/lib/position.py +15 -0
  131. pynecore/lib/request.py +281 -0
  132. pynecore/lib/runtime.py +5 -0
  133. pynecore/lib/scale.py +9 -0
  134. pynecore/lib/session.py +267 -0
  135. pynecore/lib/session.pyi +12 -0
  136. pynecore/lib/shape.py +18 -0
  137. pynecore/lib/size.py +12 -0
  138. pynecore/lib/splits.py +4 -0
  139. pynecore/lib/strategy/__init__.py +4778 -0
  140. pynecore/lib/strategy/closedtrades.py +347 -0
  141. pynecore/lib/strategy/closedtrades.pyi +53 -0
  142. pynecore/lib/strategy/commission.py +9 -0
  143. pynecore/lib/strategy/direction.py +9 -0
  144. pynecore/lib/strategy/oca.py +13 -0
  145. pynecore/lib/strategy/opentrades.py +281 -0
  146. pynecore/lib/strategy/opentrades.pyi +49 -0
  147. pynecore/lib/strategy/risk.py +109 -0
  148. pynecore/lib/string.py +649 -0
  149. pynecore/lib/syminfo.py +84 -0
  150. pynecore/lib/ta.py +2230 -0
  151. pynecore/lib/table.py +290 -0
  152. pynecore/lib/text.py +17 -0
  153. pynecore/lib/ticker.py +207 -0
  154. pynecore/lib/timeframe.py +293 -0
  155. pynecore/lib/volume_row.py +67 -0
  156. pynecore/lib/xloc.py +4 -0
  157. pynecore/lib/yloc.py +5 -0
  158. pynecore/providers/__init__.py +0 -0
  159. pynecore/providers/ccxt.py +664 -0
  160. pynecore/providers/replay.py +187 -0
  161. pynecore/pynesys/__init__.py +0 -0
  162. pynecore/pynesys/api.py +498 -0
  163. pynecore/pynesys/compiler.py +112 -0
  164. pynecore/standalone.py +99 -0
  165. pynecore/testing/__init__.py +1 -0
  166. pynecore/testing/broker_lab/__init__.py +41 -0
  167. pynecore/testing/broker_lab/__main__.py +5 -0
  168. pynecore/testing/broker_lab/cli.py +87 -0
  169. pynecore/testing/broker_lab/generate.py +47 -0
  170. pynecore/testing/broker_lab/model.py +84 -0
  171. pynecore/testing/broker_lab/reference.py +645 -0
  172. pynecore/testing/broker_lab/runner.py +372 -0
  173. pynecore/testing/broker_lab/scheduler.py +50 -0
  174. pynecore/testing/broker_lab/subprocess.py +73 -0
  175. pynecore/transformers/__init__.py +0 -0
  176. pynecore/transformers/builtin_shadow.py +136 -0
  177. pynecore/transformers/closure_arguments_transformer.py +428 -0
  178. pynecore/transformers/display_rewrite.py +140 -0
  179. pynecore/transformers/dynamic_default.py +147 -0
  180. pynecore/transformers/function_isolation.py +757 -0
  181. pynecore/transformers/import_lifter.py +61 -0
  182. pynecore/transformers/import_normalizer.py +328 -0
  183. pynecore/transformers/inline_series_hoist.py +178 -0
  184. pynecore/transformers/input_transformer.py +175 -0
  185. pynecore/transformers/lib_series.py +201 -0
  186. pynecore/transformers/locations.py +70 -0
  187. pynecore/transformers/module_properties.json +3387 -0
  188. pynecore/transformers/module_property.py +221 -0
  189. pynecore/transformers/ne_guard.py +70 -0
  190. pynecore/transformers/persistent.py +320 -0
  191. pynecore/transformers/persistent_series.py +76 -0
  192. pynecore/transformers/safe_convert_transformer.py +97 -0
  193. pynecore/transformers/safe_division_transformer.py +95 -0
  194. pynecore/transformers/script_requirements.py +308 -0
  195. pynecore/transformers/security.py +752 -0
  196. pynecore/transformers/security_instantiation.py +274 -0
  197. pynecore/transformers/series.py +275 -0
  198. pynecore/transformers/slot_layout.py +381 -0
  199. pynecore/transformers/type_checking_stripper.py +25 -0
  200. pynecore/transformers/unused_series_detector.py +267 -0
  201. pynecore/types/__init__.py +21 -0
  202. pynecore/types/alert.py +5 -0
  203. pynecore/types/barmerge.py +5 -0
  204. pynecore/types/base.py +39 -0
  205. pynecore/types/box.py +37 -0
  206. pynecore/types/chart.py +17 -0
  207. pynecore/types/color.py +107 -0
  208. pynecore/types/currency.py +5 -0
  209. pynecore/types/datetime.py +6 -0
  210. pynecore/types/display.py +5 -0
  211. pynecore/types/dividends.py +5 -0
  212. pynecore/types/earnings.py +5 -0
  213. pynecore/types/extend.py +5 -0
  214. pynecore/types/font.py +5 -0
  215. pynecore/types/footprint.py +41 -0
  216. pynecore/types/format.py +5 -0
  217. pynecore/types/hline.py +24 -0
  218. pynecore/types/ib_persistent.py +8 -0
  219. pynecore/types/ib_persistent.pyi +10 -0
  220. pynecore/types/label.py +35 -0
  221. pynecore/types/line.py +32 -0
  222. pynecore/types/linefill.py +13 -0
  223. pynecore/types/location.py +5 -0
  224. pynecore/types/matrix.py +999 -0
  225. pynecore/types/na.py +237 -0
  226. pynecore/types/na.pyi +83 -0
  227. pynecore/types/ohlcv.py +12 -0
  228. pynecore/types/order.py +5 -0
  229. pynecore/types/persistent.py +8 -0
  230. pynecore/types/persistent.pyi +13 -0
  231. pynecore/types/pine_types.py +11 -0
  232. pynecore/types/pine_types.pyi +15 -0
  233. pynecore/types/pivotpointtype.py +5 -0
  234. pynecore/types/plot.py +12 -0
  235. pynecore/types/plot_meta.py +60 -0
  236. pynecore/types/polyline.py +40 -0
  237. pynecore/types/position.py +5 -0
  238. pynecore/types/scale.py +5 -0
  239. pynecore/types/script_type.py +15 -0
  240. pynecore/types/series.py +23 -0
  241. pynecore/types/series.pyi +19 -0
  242. pynecore/types/session.py +35 -0
  243. pynecore/types/shape.py +5 -0
  244. pynecore/types/size.py +5 -0
  245. pynecore/types/source.py +33 -0
  246. pynecore/types/splits.py +5 -0
  247. pynecore/types/strategy.py +45 -0
  248. pynecore/types/table.py +87 -0
  249. pynecore/types/text.py +13 -0
  250. pynecore/types/type_checker.py +7 -0
  251. pynecore/types/type_checker.pyi +48 -0
  252. pynecore/types/volume_row.py +36 -0
  253. pynecore/types/weekdays.py +11 -0
  254. pynecore/types/xloc.py +5 -0
  255. pynecore/types/yloc.py +5 -0
  256. pynecore/utils/__init__.py +0 -0
  257. pynecore/utils/file_utils.py +50 -0
  258. pynecore/utils/rich/__init__.py +0 -0
  259. pynecore/utils/rich/date_column.py +25 -0
  260. pynecore/utils/sequence_view.py +92 -0
  261. pynecore/utils/stdlib_checker.py +17 -0
@@ -0,0 +1,60 @@
1
+ """
2
+ ``barmerge`` namespace — gap and lookahead modes for ``request.security()``.
3
+
4
+ Gap modes
5
+ ---------
6
+
7
+ - ``gaps_off``: forward-fill missing values (default)
8
+ - ``gaps_on``: emit ``na`` between security periods
9
+
10
+ Lookahead modes
11
+ ---------------
12
+
13
+ PyneCore exposes three lookahead-mode constants. Pine v6's ``lookahead_off``
14
+ and ``lookahead_on`` are kept for source-level compatibility with TradingView
15
+ scripts; ``lookahead_last_closed`` is a PyneSys-native alternative.
16
+
17
+ - ``lookahead_off`` (default): TV-faithful closed-bar behavior — the security
18
+ context advances only to the bar that has CLOSED at or before the chart
19
+ bar's time. In historical mode this matches TradingView exactly. In live
20
+ mode every HTF period close is shipped to the subprocess via the chart-side
21
+ ``HTFAggregator`` (the static ``.ohlcv`` file cannot grow at runtime); no
22
+ developing-bar exposure. Note: PyneCore's ``lookahead_off`` is intentionally
23
+ repaint-free even in live mode — it does not mirror TV's live developing
24
+ exposure for ``lookahead_off + close[0]``.
25
+
26
+ - ``lookahead_last_closed`` (PyneSys-native): always returns the most recently
27
+ closed security bar. In historical mode it is functionally equivalent to
28
+ ``lookahead_off``; in live mode it uses the same closed-bar transport as
29
+ ``lookahead_off`` and stays repaint-free (no in-progress bar). Preferred
30
+ when you want explicit "last closed" semantics without depending on the TV
31
+ ``close[1]`` idiom.
32
+
33
+ - ``lookahead_on``: TV-compatible. In live mode the security subprocess steps
34
+ into the containing HTF bar with ``barstate.isconfirmed=False`` and OHLCV
35
+ aggregated from chart-timeframe data — matching TradingView's developing-bar
36
+ semantics, so the TV idiom ``request.security(..., lookahead_on)[1]`` returns
37
+ the latest closed value as it does on TV. In historical mode it falls back
38
+ to closed-only semantics (equivalent to ``lookahead_off``), so historical
39
+ backtests never expose a developing close.
40
+
41
+ Cross-symbol HTF ``lookahead_*`` in live mode is bounded by chart-symbol
42
+ aggregation: only same-symbol HTF contexts get the live HTF transport. Cross-symbol
43
+ HTF ``lookahead_off`` / ``lookahead_last_closed`` read closed bars from the
44
+ security's own data feed. Cross-symbol HTF ``lookahead_on`` returns ``na`` for
45
+ the current chart bar inside an open HTF period (the developing bar cannot be
46
+ aggregated from the wrong instrument); ``close[1]`` at the period boundary
47
+ still delivers the just-closed cross-symbol HTF close, preserving the TV
48
+ ``lookahead_on + close[1]`` idiom.
49
+ """
50
+ from ..types.barmerge import BarMerge
51
+
52
+ #
53
+ # Constants
54
+ #
55
+
56
+ gaps_off = BarMerge()
57
+ gaps_on = BarMerge()
58
+ lookahead_off = BarMerge()
59
+ lookahead_on = BarMerge()
60
+ lookahead_last_closed = BarMerge()
@@ -0,0 +1,30 @@
1
+ __all__ = [
2
+ 'isfirst',
3
+ 'islast',
4
+ 'isconfirmed',
5
+ 'ishistory',
6
+ 'islastconfirmedhistory',
7
+ 'isnew',
8
+ 'isrealtime'
9
+ ]
10
+
11
+ isfirst = True
12
+ """ Returns true if current bar is first bar in barset, false otherwise."""
13
+
14
+ islast = False
15
+ """ Returns true if current bar is the last bar in barset, false otherwise. """
16
+
17
+ isconfirmed = True
18
+ """ Returns true if the script is calculating the last (closing) update of the current bar. """
19
+
20
+ ishistory = True
21
+ """ Returns true if script is calculating on historical bars, false otherwise. """
22
+
23
+ islastconfirmedhistory = False
24
+ """ Returns true on the last historical bar before real-time bars begin. """
25
+
26
+ isnew = False
27
+ """ Returns true if script is currently calculating on new bar, false otherwise. """
28
+
29
+ isrealtime = False
30
+ """ Returns true if script is calculating on real-time bars, false otherwise. """
pynecore/lib/box.py ADDED
@@ -0,0 +1,415 @@
1
+ from copy import copy as _copy
2
+ from typing import Any, overload
3
+
4
+ from ..core.module_property import module_property
5
+
6
+ from ..types.base import next_vid
7
+ from ..types.box import Box
8
+ from ..types.na import NA, na_int, na_float
9
+ from ..types.pine_types import PyneFloat, PyneInt
10
+ from ..types.chart import ChartPoint
11
+ from ..lib import (color as _color, extend as _extend, xloc as _xloc, size as _size, line as _line,
12
+ text as _text, font as _font)
13
+ from .. import lib
14
+
15
+ _registry: dict[Box, None] = {}
16
+
17
+
18
+ @overload
19
+ def new(top_left: ChartPoint, bottom_right: ChartPoint, border_color: _color.Color = _color.blue,
20
+ border_width: int = 1, border_style: _line.LineEnum = _line.style_solid,
21
+ extend: _extend.Extend = _extend.none, xloc: _xloc.XLoc = _xloc.bar_index,
22
+ bgcolor: _color.Color = _color.blue, text: str = "", text_size: _size.Size = _size.auto,
23
+ text_color: _color.Color = _color.black, text_halign: _text.AlignEnum = _text.align_center,
24
+ text_valign: _text.AlignEnum = _text.align_center, text_wrap: _text.WrapEnum = _text.wrap_none,
25
+ text_font_family: _font.FontFamilyEnum = _font.family_default, force_overlay: bool = False,
26
+ text_formatting: _text.FormatEnum = _text.format_none) -> Box: ...
27
+
28
+
29
+ @overload
30
+ def new(left: int | float, top: float, right: int | float, bottom: float,
31
+ border_color: _color.Color = _color.blue, border_width: int = 1,
32
+ border_style: _line.LineEnum = _line.style_solid, extend: _extend.Extend = _extend.none,
33
+ xloc: _xloc.XLoc = _xloc.bar_index, bgcolor: _color.Color = _color.blue, text: str = "",
34
+ text_size: _size.Size = _size.auto, text_color: _color.Color = _color.black,
35
+ text_halign: _text.AlignEnum = _text.align_center, text_valign: _text.AlignEnum = _text.align_center,
36
+ text_wrap: _text.WrapEnum = _text.wrap_none, text_font_family: _font.FontFamilyEnum = _font.family_default,
37
+ force_overlay: bool = False, text_formatting: _text.FormatEnum = _text.format_none) -> Box: ...
38
+
39
+
40
+ # Positional parameter orders of the two Pine call shapes; ``new()`` maps ``*args``
41
+ # onto one of these depending on whether the first positional is a ``chart.point``.
42
+ _COMMON_PARAMS = ('border_color', 'border_width', 'border_style', 'extend', 'xloc', 'bgcolor',
43
+ 'text', 'text_size', 'text_color', 'text_halign', 'text_valign', 'text_wrap',
44
+ 'text_font_family', 'force_overlay', 'text_formatting')
45
+ _POINT_PARAMS = ('top_left', 'bottom_right') + _COMMON_PARAMS
46
+ _COORD_PARAMS = ('left', 'top', 'right', 'bottom') + _COMMON_PARAMS
47
+
48
+
49
+ # noinspection PyProtectedMember
50
+ def new(*args: Any, **kwargs: Any) -> Box:
51
+ """
52
+ Creates a new box object.
53
+
54
+ Two call shapes are accepted (Pine-compatible):
55
+ - ``box.new(top_left, bottom_right, ...)`` where both arguments are ``chart.point`` objects
56
+ (the top-left and bottom-right corners).
57
+ - ``box.new(left, top, right, bottom, ...)`` where ``left`` / ``right`` are bar index
58
+ (``xloc.bar_index``) or bar UNIX time in milliseconds (``xloc.bar_time``),
59
+ and ``top`` / ``bottom`` are prices. Float ``left`` / ``right`` are truncated
60
+ to int to mirror Pine's implicit float-to-int conversion on ``series int`` parameters.
61
+
62
+ :param left: Bar index / bar time of the left border (coordinate form)
63
+ :param top: Price of the top border (coordinate form)
64
+ :param right: Bar index / bar time of the right border (coordinate form only)
65
+ :param bottom: Price of the bottom border (coordinate form only)
66
+ :param border_color: Color of the four borders
67
+ :param border_width: Width of the four borders, in pixels
68
+ :param border_style: Style of the four borders
69
+ :param extend: When ``extend.none`` is used, the horizontal borders start at the left border and end at the right border
70
+ :param xloc: Determines whether ``left`` / ``right`` are a bar index or a bar time value
71
+ :param bgcolor: Background color of the box
72
+ :param text: The text to be displayed inside the box
73
+ :param text_size: Size of the box's text
74
+ :param text_color: The color of the text
75
+ :param text_halign: The horizontal alignment of the box's text
76
+ :param text_valign: The vertical alignment of the box's text
77
+ :param text_wrap: Whether to wrap text. Wrapped text starts a new line
78
+ :param text_font_family: The font family of the text
79
+ :param force_overlay: If true, the drawing will display on the main chart pane
80
+ :param text_formatting: The formatting of the displayed text
81
+ :param top_left: Top-left corner ``chart.point`` (point form, keyword equivalent of the first positional)
82
+ :param bottom_right: Bottom-right corner ``chart.point`` (point form, keyword equivalent of the second positional)
83
+ :return: A box object
84
+ """
85
+ if args:
86
+ names = _POINT_PARAMS if isinstance(args[0], ChartPoint) else _COORD_PARAMS
87
+ if len(args) > len(names):
88
+ raise TypeError(f"box.new() takes at most {len(names)} positional arguments")
89
+ for name, value in zip(names, args):
90
+ if name in kwargs:
91
+ raise TypeError(f"box.new() got multiple values for argument '{name}'")
92
+ kwargs[name] = value
93
+ top_left = kwargs.get('top_left')
94
+ bottom_right = kwargs.get('bottom_right')
95
+ border_color = kwargs.get('border_color', _color.blue)
96
+ border_width = kwargs.get('border_width', 1)
97
+ border_style = kwargs.get('border_style', _line.style_solid)
98
+ extend = kwargs.get('extend', _extend.none)
99
+ xloc = kwargs.get('xloc', _xloc.bar_index)
100
+ bgcolor = kwargs.get('bgcolor', _color.blue)
101
+ text = kwargs.get('text', "")
102
+ text_size = kwargs.get('text_size', _size.auto)
103
+ text_color = kwargs.get('text_color', _color.black)
104
+ text_halign = kwargs.get('text_halign', _text.align_center)
105
+ text_valign = kwargs.get('text_valign', _text.align_center)
106
+ text_wrap = kwargs.get('text_wrap', _text.wrap_none)
107
+ text_font_family = kwargs.get('text_font_family', _font.family_default)
108
+ force_overlay = kwargs.get('force_overlay', False)
109
+ text_formatting = kwargs.get('text_formatting', _text.format_none)
110
+ if isinstance(top_left, ChartPoint):
111
+ bottom_right_point = bottom_right if isinstance(bottom_right, ChartPoint) else top_left
112
+ if xloc == _xloc.bar_time:
113
+ left_val, top_val = top_left.time, top_left.price
114
+ right_val, bottom_val = bottom_right_point.time, bottom_right_point.price
115
+ else:
116
+ left_val, top_val = top_left.index, top_left.price
117
+ right_val, bottom_val = bottom_right_point.index, bottom_right_point.price
118
+ else:
119
+ left = kwargs.get('left')
120
+ top = kwargs.get('top')
121
+ right = kwargs.get('right')
122
+ bottom = kwargs.get('bottom')
123
+ left_val = int(left) if isinstance(left, (int, float)) and left == left else na_int
124
+ top_val = top if isinstance(top, (int, float)) else na_float
125
+ right_val = int(right) if isinstance(right, (int, float)) and right == right else na_int
126
+ bottom_val = bottom if isinstance(bottom, (int, float)) else na_float
127
+
128
+ box = Box(
129
+ left=left_val,
130
+ top=top_val,
131
+ right=right_val,
132
+ bottom=bottom_val,
133
+ border_color=border_color,
134
+ border_width=border_width,
135
+ border_style=border_style,
136
+ extend=extend,
137
+ xloc=xloc,
138
+ bgcolor=bgcolor,
139
+ text=text,
140
+ text_size=text_size,
141
+ text_color=text_color,
142
+ text_halign=text_halign,
143
+ text_valign=text_valign,
144
+ text_wrap=text_wrap,
145
+ text_font_family=text_font_family,
146
+ text_formatting=text_formatting,
147
+ force_overlay=force_overlay,
148
+ )
149
+ box.vid = next_vid()
150
+ _registry[box] = None
151
+ # Enforce Pine's max_boxes_count cap: drop the oldest box (FIFO) past the limit.
152
+ # A security child never sets ``lib._script``; fall back to TV's hard maximum
153
+ # (500) there, otherwise the registry grows without bound (the child re-runs
154
+ # main() for every bar of its own series, accumulating every drawing ever made).
155
+ if len(_registry) > (lib._script.max_boxes_count if lib._script is not None else 500):
156
+ del _registry[next(iter(_registry))]
157
+ return box
158
+
159
+
160
+ # noinspection PyShadowingBuiltins
161
+ @module_property
162
+ def all() -> list[Box]:
163
+ """Returns all box objects"""
164
+ return list(_registry)
165
+
166
+
167
+ # noinspection PyShadowingBuiltins
168
+ def delete(id):
169
+ if isinstance(id, NA):
170
+ return
171
+ _registry.pop(id, None)
172
+
173
+
174
+ # noinspection PyShadowingBuiltins,PyProtectedMember
175
+ def copy(id):
176
+ if isinstance(id, NA):
177
+ return NA(Box)
178
+ clone = _copy(id)
179
+ clone.vid = next_vid()
180
+ _registry[clone] = None
181
+ if len(_registry) > (lib._script.max_boxes_count if lib._script is not None else 500):
182
+ del _registry[next(iter(_registry))]
183
+ return clone
184
+
185
+
186
+ # Setter methods
187
+
188
+ # noinspection PyShadowingBuiltins
189
+ def set_bgcolor(id: Box, color: _color.Color) -> None:
190
+ """Sets the background color of the box."""
191
+ if isinstance(id, NA):
192
+ return
193
+ id.bgcolor = color
194
+
195
+
196
+ # noinspection PyShadowingBuiltins
197
+ def set_border_color(id: Box, color: _color.Color) -> None:
198
+ """Sets the border color of the box."""
199
+ if isinstance(id, NA):
200
+ return
201
+ id.border_color = color
202
+
203
+
204
+ # noinspection PyShadowingBuiltins
205
+ def set_border_style(id: Box, style: _line.LineEnum) -> None:
206
+ """Sets the border style of the box."""
207
+ if isinstance(id, NA):
208
+ return
209
+ id.border_style = style
210
+
211
+
212
+ # noinspection PyShadowingBuiltins
213
+ def set_border_width(id: Box, width: int) -> None:
214
+ """Sets the border width of the box."""
215
+ if isinstance(id, NA):
216
+ return
217
+ id.border_width = width
218
+
219
+
220
+ # noinspection PyShadowingBuiltins
221
+ def set_bottom(id: Box, bottom: float) -> None:
222
+ """Sets the bottom coordinate of the box."""
223
+ if isinstance(id, NA):
224
+ return
225
+ id.bottom = bottom
226
+
227
+
228
+ # noinspection PyShadowingBuiltins
229
+ def set_bottom_right_point(id: Box, point: ChartPoint) -> None:
230
+ """Sets the bottom-right corner location of the box to point."""
231
+ if isinstance(id, NA):
232
+ return
233
+ if id.xloc == _xloc.bar_time:
234
+ id.right = point.time
235
+ else:
236
+ id.right = point.index
237
+ id.bottom = point.price
238
+
239
+
240
+ # noinspection PyShadowingBuiltins
241
+ def set_extend(id: Box, extend: _extend.Extend) -> None:
242
+ """Sets extending type of the border of this box object."""
243
+ if isinstance(id, NA):
244
+ return
245
+ id.extend = extend
246
+
247
+
248
+ # noinspection PyShadowingBuiltins
249
+ def set_left(id: Box, left: int) -> None:
250
+ """Sets the left coordinate of the box."""
251
+ if isinstance(id, NA):
252
+ return
253
+ id.left = left
254
+
255
+
256
+ # noinspection PyShadowingBuiltins
257
+ def set_lefttop(id: Box, left: int, top: float) -> None:
258
+ """Sets the left and top coordinates of the box."""
259
+ if isinstance(id, NA):
260
+ return
261
+ id.left = left
262
+ id.top = top
263
+
264
+
265
+ # noinspection PyShadowingBuiltins
266
+ def set_right(id: Box, right: int) -> None:
267
+ """Sets the right coordinate of the box."""
268
+ if isinstance(id, NA):
269
+ return
270
+ id.right = right
271
+
272
+
273
+ # noinspection PyShadowingBuiltins
274
+ def set_rightbottom(id: Box, right: int, bottom: float) -> None:
275
+ """Sets the right and bottom coordinates of the box."""
276
+ if isinstance(id, NA):
277
+ return
278
+ id.right = right
279
+ id.bottom = bottom
280
+
281
+
282
+ # noinspection PyShadowingBuiltins
283
+
284
+
285
+ def set_text(id: Box, text: str) -> None:
286
+ """Sets the text in the box."""
287
+ if isinstance(id, NA):
288
+ return
289
+ id.text = text
290
+
291
+
292
+ # noinspection PyShadowingBuiltins
293
+ def set_text_color(id: Box, text_color: _color.Color) -> None:
294
+ """Sets the color of the text inside the box."""
295
+ if isinstance(id, NA):
296
+ return
297
+ id.text_color = text_color
298
+
299
+
300
+ # noinspection PyShadowingBuiltins
301
+ def set_text_font_family(id: Box, text_font_family: _font.FontFamilyEnum) -> None:
302
+ """Sets the font family of the text inside the box."""
303
+ if isinstance(id, NA):
304
+ return
305
+ id.text_font_family = text_font_family
306
+
307
+
308
+ # noinspection PyShadowingBuiltins
309
+ def set_text_formatting(id: Box, text_formatting: _text.FormatEnum) -> None:
310
+ """Sets the formatting attributes the drawing applies to displayed text."""
311
+ if isinstance(id, NA):
312
+ return
313
+ id.text_formatting = text_formatting
314
+
315
+
316
+ # noinspection PyShadowingBuiltins
317
+ def set_text_halign(id: Box, text_halign: _text.AlignEnum) -> None:
318
+ """Sets the horizontal alignment of the box's text."""
319
+ if isinstance(id, NA):
320
+ return
321
+ id.text_halign = text_halign
322
+
323
+
324
+ # noinspection PyShadowingBuiltins
325
+ def set_text_size(id: Box, text_size: _size.Size) -> None:
326
+ """Sets the size of the box's text."""
327
+ if isinstance(id, NA):
328
+ return
329
+ id.text_size = text_size
330
+
331
+
332
+ # noinspection PyShadowingBuiltins
333
+ def set_text_valign(id: Box, text_valign: _text.AlignEnum) -> None:
334
+ """Sets the vertical alignment of the box's text."""
335
+ if isinstance(id, NA):
336
+ return
337
+ id.text_valign = text_valign
338
+
339
+
340
+ # noinspection PyShadowingBuiltins
341
+ def set_text_wrap(id: Box, text_wrap: _text.WrapEnum) -> None:
342
+ """Sets the mode of wrapping of the text inside the box."""
343
+ if isinstance(id, NA):
344
+ return
345
+ id.text_wrap = text_wrap
346
+
347
+
348
+ # noinspection PyShadowingBuiltins
349
+ def set_top(id: Box, top: float) -> None:
350
+ """Sets the top coordinate of the box."""
351
+ if isinstance(id, NA):
352
+ return
353
+ id.top = top
354
+
355
+
356
+ # noinspection PyShadowingBuiltins
357
+ def set_top_left_point(id: Box, point: ChartPoint) -> None:
358
+ """Sets the top-left corner location of the box to point."""
359
+ if isinstance(id, NA):
360
+ return
361
+ if id.xloc == _xloc.bar_time:
362
+ id.left = point.time
363
+ else:
364
+ id.left = point.index
365
+ id.top = point.price
366
+
367
+
368
+ # noinspection PyShadowingBuiltins
369
+ def set_xloc(id: Box, left: int, right: int, xloc: _xloc.XLoc) -> None:
370
+ """Sets the left and right borders of a box and updates its xloc property."""
371
+ if isinstance(id, NA):
372
+ return
373
+ id.left = left
374
+ id.right = right
375
+ id.xloc = xloc
376
+
377
+
378
+ # Getter methods
379
+
380
+ # noinspection PyShadowingBuiltins
381
+ def get_bottom(id: Box) -> PyneFloat:
382
+ """Returns the price value of the bottom border of the box."""
383
+ if isinstance(id, NA):
384
+ return na_float
385
+ return id.bottom
386
+
387
+
388
+ # noinspection PyShadowingBuiltins
389
+ def get_left(id: Box) -> PyneInt:
390
+ """
391
+ Returns the bar index or the UNIX time (depending on the last value used for 'xloc') of the
392
+ left border of the box.
393
+ """
394
+ if isinstance(id, NA):
395
+ return NA(int)
396
+ return id.left
397
+
398
+
399
+ # noinspection PyShadowingBuiltins
400
+ def get_right(id: Box) -> PyneInt:
401
+ """
402
+ Returns the bar index or the UNIX time (depending on the last value used for 'xloc') of the
403
+ right border of the box.
404
+ """
405
+ if isinstance(id, NA):
406
+ return NA(int)
407
+ return id.right
408
+
409
+
410
+ # noinspection PyShadowingBuiltins
411
+ def get_top(id: Box) -> PyneFloat:
412
+ """Returns the price value of the top border of the box."""
413
+ if isinstance(id, NA):
414
+ return na_float
415
+ return id.top
pynecore/lib/chart.py ADDED
@@ -0,0 +1,128 @@
1
+ from copy import copy as _copy
2
+
3
+ from ..types.color import Color
4
+ from ..types.chart import ChartPoint
5
+ from ..types.na import NA
6
+ from ..core.module_property import module_property
7
+
8
+ from .. import lib
9
+ from .timeframe import in_seconds
10
+
11
+ __all__ = [
12
+ 'bg_color',
13
+ 'fg_color',
14
+ 'is_heikinashi',
15
+ 'is_kagi',
16
+ 'is_linebreak',
17
+ 'is_pnf',
18
+ 'is_range',
19
+ 'is_renko',
20
+ 'is_standard',
21
+ 'left_visible_bar_time',
22
+ 'right_visible_bar_time',
23
+ 'point'
24
+ ]
25
+
26
+ _visible_bars = 20
27
+
28
+ bg_color = Color('#000000')
29
+ fg_color = Color('#FFFFFF')
30
+
31
+ is_heikinashi = False
32
+ is_kagi = False
33
+ is_linebreak = False
34
+ is_pnf = False
35
+ is_range = False
36
+ is_renko = False
37
+ is_standard = True
38
+
39
+
40
+ # The visible range is anchored to the chart's LAST bar (a chart scrolled to
41
+ # its right edge — TradingView's default viewport). ``lib.last_bar_time`` is
42
+ # fixed to the final bar on historical runs and tracks the realtime bar live,
43
+ # so ``time == chart.right_visible_bar_time`` is true once per historical run
44
+ # (on the final bar) and on every realtime bar — matching TV.
45
+ @module_property
46
+ def left_visible_bar_time() -> int:
47
+ return lib.last_bar_time - int(in_seconds(lib.syminfo.period) * 1000) * _visible_bars
48
+
49
+
50
+ @module_property
51
+ def right_visible_bar_time() -> int:
52
+ return lib.last_bar_time
53
+
54
+
55
+ # noinspection PyShadowingBuiltins
56
+ class _ChartPoint:
57
+ """
58
+ The ``chart.point`` constructor namespace.
59
+
60
+ A chart point holds the coordinates a drawing object uses to position itself: a bar
61
+ ``index``, a UNIX ``time`` (in milliseconds), and a ``price``. The ``xloc`` of the
62
+ consuming drawing decides which x-coordinate field is read (``index`` for
63
+ ``xloc.bar_index``, ``time`` for ``xloc.bar_time``).
64
+ """
65
+
66
+ @staticmethod
67
+ def new(time: int, index: int, price: float) -> ChartPoint:
68
+ """
69
+ Creates a new ``chart.point`` from explicit time, index, and price values.
70
+
71
+ :param time: The x-coordinate as a UNIX time value, in milliseconds
72
+ :param index: The x-coordinate as a bar index value
73
+ :param price: The y-coordinate
74
+ :return: A new chart.point object
75
+ """
76
+ return ChartPoint(index=index, time=time, price=price)
77
+
78
+ # noinspection PyProtectedMember
79
+ @staticmethod
80
+ def now(price: float) -> ChartPoint:
81
+ """
82
+ Creates a new ``chart.point`` at the current bar, using its index and time.
83
+
84
+ :param price: The y-coordinate
85
+ :return: A new chart.point object with the current bar's index and time
86
+ """
87
+ return ChartPoint(
88
+ index=int(lib.bar_index),
89
+ time=int(lib._datetime.timestamp() * 1000),
90
+ price=price
91
+ )
92
+
93
+ @staticmethod
94
+ def from_index(index: int, price: float) -> ChartPoint:
95
+ """
96
+ Creates a new ``chart.point`` from a bar index and price. The ``time`` field is ``na``.
97
+
98
+ :param index: The x-coordinate as a bar index value
99
+ :param price: The y-coordinate
100
+ :return: A new chart.point object whose ``time`` field is ``na``
101
+ """
102
+ return ChartPoint(index=index, time=NA(int), price=price)
103
+
104
+ @staticmethod
105
+ def from_time(time: int, price: float) -> ChartPoint:
106
+ """
107
+ Creates a new ``chart.point`` from a UNIX time and price. The ``index`` field is ``na``.
108
+
109
+ :param time: The x-coordinate as a UNIX time value, in milliseconds
110
+ :param price: The y-coordinate
111
+ :return: A new chart.point object whose ``index`` field is ``na``
112
+ """
113
+ return ChartPoint(index=NA(int), time=time, price=price)
114
+
115
+ @staticmethod
116
+ def copy(id: ChartPoint) -> ChartPoint:
117
+ """
118
+ Returns a copy of the ``chart.point`` object.
119
+
120
+ :param id: The chart.point object to copy
121
+ :return: A new chart.point object with the same field values
122
+ """
123
+ if isinstance(id, NA):
124
+ return NA(ChartPoint)
125
+ return _copy(id)
126
+
127
+
128
+ point = _ChartPoint()