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,1011 @@
1
+ from typing import Any, Callable, TypeVar, overload
2
+ import os
3
+ import sys
4
+
5
+ from dataclasses import dataclass, field
6
+ from enum import StrEnum
7
+ from pathlib import Path
8
+
9
+ import pynecore.lib.format as _format
10
+ import pynecore.lib.scale as _scale
11
+ import pynecore.lib.strategy as _strategy
12
+ import pynecore.lib.currency as _currency
13
+ import pynecore.lib.display as _display
14
+
15
+ from pynecore.core.broker.models import ScriptRequirements
16
+
17
+ from pynecore.types import script_type as _script_type
18
+ from pynecore.types.color import Color
19
+ from pynecore.types import PyneFloat, PyneInt
20
+
21
+ __all__ = ['script', 'input']
22
+
23
+ from pynecore.types.source import Source
24
+ from . import safe_convert
25
+
26
+ # Global registry for library main functions
27
+ _registered_libraries: list[tuple[str, Callable]] = []
28
+
29
+ # TypeVar for enum type preservation
30
+ TEnum = TypeVar('TEnum', bound=StrEnum)
31
+
32
+
33
+ @dataclass(kw_only=True, slots=True)
34
+ class InputData:
35
+ """
36
+ Input dataclass
37
+ """
38
+ id: str | None = None
39
+ input_type: str | None = None
40
+ defval: int | bool | Color | float | str | None = None
41
+ title: str | None = None
42
+ minval: int | float | None = None
43
+ maxval: int | float | None = None
44
+ step: int | float | None = None
45
+ tooltip: str | None = None
46
+ inline: str | None = None
47
+ group: str | None = None
48
+ confirm: bool | None = False
49
+ options: tuple[int | float | str, ...] | None = None
50
+ display: _display.Display | None = None
51
+
52
+
53
+ _old_input_values: dict[str, Any] = {}
54
+ _programmatic_inputs: dict[str, Any] = {}
55
+ inputs: dict[str, InputData] = {}
56
+
57
+
58
+ # noinspection PyShadowingBuiltins,PyShadowingNames,PyDunderSlots,PyUnresolvedReferences
59
+ @dataclass(kw_only=True, slots=True)
60
+ class Script:
61
+ """
62
+ Script parameters dataclass
63
+ """
64
+ # These fields will be skipped when saving to toml
65
+ _SKIP_FIELDS = {'script_type', 'inputs', 'title', 'shorttitle', 'position'}
66
+
67
+ script_type: _script_type.ScriptType | None = None
68
+ inputs: dict[str, InputData] = field(default_factory=dict)
69
+
70
+ title: str | None = None
71
+ shorttitle: str | None = None
72
+
73
+ overlay: bool = False
74
+ format: _format.Format = _format.inherit
75
+ precision: int | None = None
76
+ scale: _scale.Scale | None = None
77
+ pyramiding: int = 1
78
+ calc_on_order_fills: bool = False
79
+ calc_on_every_tick: bool = False
80
+ max_bars_back: int = 0
81
+ timeframe: str | None = None
82
+ timeframe_gaps: bool = True
83
+ explicit_plot_zorder: bool = False
84
+ max_lines_count: int = 50
85
+ max_labels_count: int = 50
86
+ max_boxes_count: int = 50
87
+ calc_bars_count: int = 0
88
+ max_polylines_count: int = 50
89
+ dynamic_requests: bool = False
90
+ behind_chart: bool = True
91
+
92
+ backtest_fill_limits_assumption: int = 0
93
+ default_qty_type: _strategy.QtyType = _strategy.cash
94
+ default_qty_value: float = 1
95
+ initial_capital: float | int = 1000000
96
+ currency: _currency.Currency = _currency.NONE
97
+ slippage: int = 0
98
+ commission_type: _strategy.commission.Commission = _strategy.commission.percent # type: ignore
99
+ commission_value: int | float = 0.0
100
+ process_orders_on_close: bool = False
101
+ close_entries_rule: str = 'FIFO'
102
+ margin_long: int | float = 100.0 # Defaulted to 100.0 in Pine Script v6
103
+ margin_short: int | float = 100.0 # Defaulted to 100.0 in Pine Script v6
104
+ risk_free_rate: float = 2.0
105
+ use_bar_magnifier: bool = True
106
+ fill_orders_on_standard_ohlc: bool = False
107
+
108
+ position: _strategy.PositionBase = None # type: ignore[assignment]
109
+
110
+ _broker_requirements: ScriptRequirements | None = None
111
+
112
+ _modified: set[str] = field(default_factory=set)
113
+
114
+ def save(self, path: Path):
115
+ """
116
+ Save script settings to TOML-like format.
117
+ Non-settable fields are commented out with '#'.
118
+ None values are also commented out.
119
+ Input values are saved with their metadata as comments.
120
+
121
+ :param path: Path to save the file
122
+ """
123
+
124
+ def _format_value(value) -> str:
125
+ """Format value according to its type"""
126
+ if isinstance(value, bool):
127
+ return str(value).lower()
128
+ if isinstance(value, (int, float)):
129
+ return str(value)
130
+ if isinstance(value, Color):
131
+ value = str(value)
132
+ if isinstance(value, str):
133
+ # Escape newlines and backslashes for valid TOML
134
+ escaped = value.replace('\\', '\\\\').replace('\n', '\\n').replace('\r', '\\r')
135
+ return f'"{escaped}"'
136
+ return str(value)
137
+
138
+ lines = [
139
+ "# Indicator / Strategy / Library Settings",
140
+ "",
141
+ "[script]"
142
+ ]
143
+
144
+ # Save general settings
145
+ from dataclasses import fields
146
+ for field in fields(self):
147
+ key = field.name
148
+ value = getattr(self, key)
149
+ if key.startswith('_') or key in self._SKIP_FIELDS:
150
+ continue
151
+ if value is None:
152
+ line = f"#{key} ="
153
+ else:
154
+ line = "#" if key not in self._modified else ""
155
+ line += f"{key} = {_format_value(value)}"
156
+ lines.append(line)
157
+
158
+ # Add an empty line before inputs
159
+ lines.append("")
160
+ lines.append("# Input Settings")
161
+
162
+ # Save inputs
163
+ for arg_name, input_data in self.inputs.items():
164
+ if not arg_name:
165
+ continue
166
+ lines.append(f"\n[inputs.{arg_name.removesuffix('__global__')}]")
167
+ lines.append("# Input metadata, cannot be modified")
168
+
169
+ # Add all metadata as comments
170
+ from dataclasses import fields as input_fields
171
+ for field in input_fields(input_data):
172
+ key = field.name
173
+ value = getattr(input_data, key)
174
+ if key == 'id':
175
+ continue
176
+ if value is not None:
177
+ # We use ':` to not confuse with real values
178
+ lines.append(f"# {key.rjust(10)}: {_format_value(value)}")
179
+
180
+ lines.append("# Change here to modify the input value")
181
+
182
+ # Add the actual value
183
+ if input_data.defval is not None and arg_name in _old_input_values:
184
+ lines.append(f"value = {_format_value(_old_input_values[arg_name])}")
185
+ else:
186
+ lines.append("#value =")
187
+
188
+ # Write to file
189
+ with open(path, 'w', encoding='utf-8') as f:
190
+ f.write('\n'.join(lines) + '\n')
191
+
192
+ def load(self, path: str | Path) -> None:
193
+ """
194
+ Load script settings from TOML file and update this script instance.
195
+ Only loads settable fields and input values, preserving the original script structure.
196
+
197
+ :param path: Path to load the file from
198
+ """
199
+ import tomllib
200
+
201
+ with open(path, 'rb') as f:
202
+ data = tomllib.load(f)
203
+
204
+ if 'script' not in data:
205
+ raise ValueError("Invalid TOML: missing [script] section!")
206
+
207
+ script_data = data['script']
208
+
209
+ for key, value in script_data.items():
210
+ if key not in self._SKIP_FIELDS and hasattr(self, key):
211
+ if value != getattr(self, key):
212
+ setattr(self, key, value)
213
+ # We just save the modified fields
214
+ self._modified.add(key)
215
+
216
+ if 'inputs' not in data:
217
+ return
218
+
219
+ # Fill old_input_values
220
+ for arg_name, arg_data in data['inputs'].items():
221
+ if 'value' not in arg_data:
222
+ continue
223
+ _old_input_values[arg_name] = arg_data['value']
224
+ _old_input_values[arg_name + '__global__'] = arg_data['value'] # For strict mode
225
+
226
+ #
227
+ # decorators
228
+ #
229
+
230
+ def _decorate(self):
231
+ # Get the script path from the caller frame
232
+ script_path = Path(sys._getframe(2).f_globals['__file__']).resolve() # noqa F821
233
+ toml_path = script_path.with_suffix('.toml')
234
+
235
+ # Load settings from toml file if exists
236
+ if toml_path.exists():
237
+ self.load(toml_path)
238
+
239
+ # Apply programmatic inputs (override .toml values)
240
+ if _programmatic_inputs:
241
+ for key, value in _programmatic_inputs.items():
242
+ _old_input_values[key] = value
243
+ _old_input_values[key + '__global__'] = value
244
+ _programmatic_inputs.clear()
245
+
246
+ # Pyramiding must be at least 1
247
+ if self.pyramiding <= 0:
248
+ self.pyramiding = 1
249
+
250
+ def decorator(func):
251
+ # Save inputs to script instance then clear inputs (for next script)
252
+ self.inputs = inputs.copy() # type: ignore
253
+ inputs.clear()
254
+
255
+ # Set script attribute to the main function to be able to access script properties
256
+ setattr(func, 'script', self)
257
+
258
+ if self.script_type in (_script_type.indicator, _script_type.strategy):
259
+ # Save toml file if not in pytest and not disabled by env var PYNE_SAVE_SCRIPT_TOML = 0
260
+ if os.environ.get('PYNE_SAVE_SCRIPT_TOML', '1') == '1' and 'pytest' not in sys.modules:
261
+ self.save(toml_path)
262
+
263
+ _old_input_values.clear()
264
+ return func
265
+
266
+ return decorator
267
+
268
+ # noinspection DuplicatedCode
269
+ @classmethod
270
+ def indicator(
271
+ cls,
272
+ title='', shorttitle='',
273
+ overlay=False,
274
+ format: _format.Format = _format.inherit,
275
+ precision: int | None = None,
276
+ scale: _scale.Scale | None = None,
277
+ max_bars_back=0,
278
+ timeframe: str | None = None,
279
+ timeframe_gaps=True,
280
+ explicit_plot_zorder=False,
281
+ max_lines_count=50,
282
+ max_labels_count=50,
283
+ max_boxes_count=50,
284
+ calc_bars_count=0,
285
+ max_polylines_count=50,
286
+ dynamic_requests=False,
287
+ behind_chart=True,
288
+ *_, **__
289
+ ) -> Callable[..., Any]:
290
+ """
291
+ Decorator for indicator script. You should deocrate `main` function with this decorator if
292
+ your script is an indicator script.
293
+
294
+ :param title: The title of the script
295
+ :param shorttitle: The script's display name
296
+ :param overlay: If True, the script will be displayed on the price chart as an overlay,
297
+ otherwise it will be displayed in a separate pane
298
+ :param format: Specifies the formatting of the script's displayed values
299
+ :param precision: Specifies the number of digits after the floating point of the script's displayed values
300
+ :param scale: The price scale used
301
+ :param max_bars_back: The length of the historical buffer the script keeps for every
302
+ Series variables which determines how many past values can be
303
+ referenced by Series objects
304
+ :param timeframe: Adds multi-timeframe functionality to simple scripts
305
+ :param timeframe_gaps: Specifies how the indicator's values are displayed on chart bars
306
+ when the `timeframe` is higher than the chart's timeframe.
307
+ :param explicit_plot_zorder: Specifies the order in which the script's plots, fills, and hlines are rendered
308
+ :param max_lines_count: The number of last line drawings displayed on the chart
309
+ :param max_labels_count: The number of last label drawings displayed
310
+ :param max_boxes_count: The number of last box drawings displayed
311
+ :param calc_bars_count: Limits the initial calculation of a script to the last number of bars specified
312
+ :param max_polylines_count: The number of last polyline drawings displayed
313
+ :param dynamic_requests: Specifies whether the script can dynamically call functions from
314
+ the `request.*()` namespace
315
+ :param behind_chart: Controls whether the script's plots and drawings in the main chart pane
316
+ appear behind the chart display
317
+ """
318
+ script = cls()
319
+ script.script_type = _script_type.indicator
320
+ script.title = title
321
+ script.shorttitle = shorttitle
322
+
323
+ script.overlay = overlay
324
+ script.format = format
325
+ script.precision = precision
326
+ script.scale = scale
327
+ script.max_bars_back = max_bars_back
328
+ script.timeframe = timeframe
329
+ script.timeframe_gaps = timeframe_gaps
330
+ script.explicit_plot_zorder = explicit_plot_zorder
331
+ script.max_lines_count = max_lines_count
332
+ script.max_labels_count = max_labels_count
333
+ script.max_boxes_count = max_boxes_count
334
+ script.calc_bars_count = calc_bars_count
335
+ script.max_polylines_count = max_polylines_count
336
+ script.dynamic_requests = dynamic_requests
337
+ script.behind_chart = behind_chart
338
+
339
+ return script._decorate()
340
+
341
+ # noinspection DuplicatedCode
342
+ @classmethod
343
+ def strategy(
344
+ cls,
345
+ title='', shorttitle='',
346
+ overlay=False,
347
+ format: _format.Format = _format.inherit,
348
+ precision: int | None = None,
349
+ scale: _scale.Scale | None = None,
350
+
351
+ pyramiding: int = 0,
352
+ calc_on_order_fills=False,
353
+ calc_on_every_tick=False,
354
+
355
+ max_bars_back=0,
356
+
357
+ backtest_fill_limits_assumption=0,
358
+ default_qty_type: _strategy.QtyType = _strategy.fixed,
359
+ default_qty_value: float = 1,
360
+ initial_capital: float | int = 1000000,
361
+ currency: _currency.Currency = _currency.NONE,
362
+ slippage: int = 0,
363
+ commission_type: _strategy.commission.Commission = _strategy.commission.percent, # type: ignore
364
+ commission_value: int | float = 0.0,
365
+ process_orders_on_close=False,
366
+ close_entries_rule='FIFO',
367
+ margin_long: int | float = 100.0,
368
+ margin_short: int | float = 100.0,
369
+
370
+ explicit_plot_zorder=False,
371
+ max_lines_count=50,
372
+ max_labels_count=50,
373
+ max_boxes_count=50,
374
+ calc_bars_count=0,
375
+
376
+ risk_free_rate=2.0,
377
+ use_bar_magnifier=True,
378
+ fill_orders_on_standard_ohlc=False,
379
+
380
+ max_polylines_count=50,
381
+ dynamic_requests=False,
382
+
383
+ behind_chart=True,
384
+
385
+ _broker_requirements: ScriptRequirements | None = None,
386
+
387
+ *_, **__
388
+ ) -> Callable[..., Any]:
389
+ """
390
+ Decorator for strategy script. You should deocrate `main` function with this decorator if
391
+ your script is a strategy script.
392
+
393
+ :param title: The title of the script
394
+ :param shorttitle: The script's display name
395
+ :param overlay: If True, the script will be displayed on the price chart as an overlay,
396
+ :param format: Specifies the formatting of the script's displayed values
397
+ :param precision: Specifies the number of digits after the floating point of the script's displayed values
398
+ :param scale: The price scale used
399
+ :param pyramiding: The maximum number of entries allowed in the same direction
400
+ :param calc_on_order_fills: Specifies whether the strategy should be recalculated after an order is filled
401
+ :param calc_on_every_tick: Specifies whether the strategy should be recalculated on each realtime tick
402
+ :param max_bars_back: The length of the historical buffer the script keeps for every
403
+ :param backtest_fill_limits_assumption: Limit order execution threshold in ticks
404
+ :param default_qty_type: Specifies the units used for `default_qty_value`
405
+ :param default_qty_value: The default quantity to trade, in units determined by the argument
406
+ used with the `default_qty_type` parameter
407
+ :param initial_capital: The amount of funds initially available for the strategy to trade,
408
+ in units of `currency`
409
+ :param currency: Currency used by the strategy in currency-related calculations
410
+ :param slippage: Slippage expressed in ticks
411
+ :param commission_type: Determines what the number passed to the `commission_value`
412
+ :param commission_value: Commission applied to the strategy's orders in units determined by
413
+ the argument passed to the `commission_type` parameter
414
+ :param process_orders_on_close: When set to true, generates an additional attempt to execute
415
+ orders after a bar closes and strategy calculations are completed.
416
+ :param close_entries_rule: Determines the order in which trades are closed
417
+ :param margin_long: Margin long is the percentage of the purchase price of a security that
418
+ must be covered by cash or collateral for long positions
419
+ :param margin_short: Margin short is the percentage of the purchase price of a security that
420
+ must be covered by cash or collateral for short positions
421
+ :param explicit_plot_zorder: Specifies the order in which the script's plots, fills, and hlines are rendered
422
+ :param max_lines_count: The number of last line drawings displayed on the chart
423
+ :param max_labels_count: The number of last label drawings displayed
424
+ :param max_boxes_count: The number of last box drawings displayed
425
+ :param calc_bars_count: Limits the initial calculation of a script to the last number of bars specified
426
+ :param risk_free_rate: The risk-free rate of return is the annual percentage change in the
427
+ value of an investment with minimal or zero risk
428
+ :param use_bar_magnifier: When true, the Broker Emulator uses lower timeframe data during
429
+ history backtesting to achieve more realistic results
430
+ :param fill_orders_on_standard_ohlc: When true, forces strategies running on Heikin Ashi
431
+ charts to fill orders using actual OHLC prices, for more
432
+ realistic results.
433
+ :param max_polylines_count: The number of last polyline drawings displayed
434
+ :param dynamic_requests: Specifies whether the script can dynamically call functions from
435
+ :param behind_chart: Controls whether the script's plots and drawings in the main chart pane
436
+ :param _broker_requirements: Broker capability requirements of the script, internal use only
437
+ """
438
+ script = cls()
439
+ script.script_type = _script_type.strategy
440
+ script.title = title
441
+ script.shorttitle = shorttitle
442
+
443
+ script.overlay = overlay
444
+ script.format = format
445
+ script.precision = precision
446
+ script.scale = scale
447
+
448
+ script.pyramiding = pyramiding
449
+ script.calc_on_order_fills = calc_on_order_fills
450
+ script.calc_on_every_tick = calc_on_every_tick
451
+
452
+ script.max_bars_back = max_bars_back
453
+
454
+ script.backtest_fill_limits_assumption = backtest_fill_limits_assumption
455
+ script.default_qty_type = default_qty_type
456
+ script.default_qty_value = default_qty_value
457
+ script.initial_capital = initial_capital
458
+ script.currency = currency
459
+ script.slippage = slippage
460
+ script.commission_type = commission_type
461
+ script.commission_value = commission_value
462
+ script.process_orders_on_close = process_orders_on_close
463
+ script.close_entries_rule = close_entries_rule
464
+ script.margin_long = margin_long
465
+ script.margin_short = margin_short
466
+ script.explicit_plot_zorder = explicit_plot_zorder
467
+
468
+ script.max_lines_count = max_lines_count
469
+ script.max_labels_count = max_labels_count
470
+ script.max_boxes_count = max_boxes_count
471
+ script.calc_bars_count = calc_bars_count
472
+
473
+ script.risk_free_rate = risk_free_rate
474
+ script.use_bar_magnifier = use_bar_magnifier
475
+ script.fill_orders_on_standard_ohlc = fill_orders_on_standard_ohlc
476
+
477
+ script.max_polylines_count = max_polylines_count
478
+ script.dynamic_requests = dynamic_requests
479
+ script.behind_chart = behind_chart
480
+
481
+ script.position = _strategy.SimPosition()
482
+
483
+ script._broker_requirements = _broker_requirements
484
+
485
+ return script._decorate()
486
+
487
+ @classmethod
488
+ def library(
489
+ cls,
490
+ title='',
491
+ overlay=False,
492
+ dynamic_requests=False,
493
+ *_, **__
494
+ ) -> Callable[..., Any]:
495
+ """
496
+ Decorator for library script. You should deocrate `main` function with this decorator if
497
+ your script is a library script.
498
+
499
+ :param title: The title of the script
500
+ :param overlay: If True, the script will be displayed on the price chart as an overlay,
501
+ :param dynamic_requests: Specifies whether the script can dynamically call functions from
502
+ """
503
+ script = cls()
504
+ script.script_type = _script_type.library
505
+ script.title = title
506
+ script.shorttitle = title
507
+
508
+ script.overlay = overlay
509
+ script.dynamic_requests = dynamic_requests
510
+
511
+ def decorator(func):
512
+ # Register library main function if not already registered
513
+ lib_entry = (script.title or 'Untitled Library', func)
514
+ if lib_entry not in _registered_libraries:
515
+ _registered_libraries.append(lib_entry)
516
+ return script._decorate()(func)
517
+
518
+ return decorator
519
+
520
+
521
+ script = Script
522
+
523
+
524
+ class _Input:
525
+ """
526
+ Input functions
527
+ """
528
+
529
+ def __call__(self, defval: Any, title: str | None = None,
530
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
531
+ display: _display.Display | None = None, active: bool | None = None,
532
+ *, _id: str = "", **__) -> Any:
533
+ """
534
+ Adds an input to your script's settings, which allows you to provide configuration options
535
+
536
+ :param defval: The default value of the input
537
+ :param title: The title of the input
538
+ :param tooltip: The tooltip of the input
539
+ :param inline: Inputs with the same inline string are displayed on one line
540
+ :param group: The group of the input
541
+ :param display: Controls where the script will display the input's information
542
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
543
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
544
+ :return: The input value from toml file or the default
545
+ """
546
+ input_type = type(defval).__name__.lower()
547
+ if input_type == 'source':
548
+ defval = str(defval)
549
+ inputs[_id] = InputData(
550
+ id=_id,
551
+ input_type=input_type,
552
+ defval=defval,
553
+ title=title,
554
+ tooltip=tooltip,
555
+ inline=inline,
556
+ group=group,
557
+ display=display,
558
+ )
559
+ return defval if _id not in _old_input_values else _old_input_values[_id]
560
+
561
+ # Pine's numeric inputs have TWO positional overloads after ``title``: the
562
+ # minval/maxval/step form and the options form. A single Python parameter
563
+ # list cannot bind both, so the implementations take ``*args`` and bind the
564
+ # tail by inspecting the third argument (a tuple/list selects the options
565
+ # form) — mirroring what the v6 reference publishes.
566
+ _NUMERIC_RANGE_TAIL = ('minval', 'maxval', 'step', 'tooltip', 'inline', 'group',
567
+ 'confirm', 'display', 'active')
568
+ _NUMERIC_OPTIONS_TAIL = ('options', 'tooltip', 'inline', 'group',
569
+ 'confirm', 'display', 'active')
570
+
571
+ @classmethod
572
+ def _bind_numeric_tail(cls, args: tuple, kwargs: dict) -> None:
573
+ """
574
+ Bind positional arguments after ``title`` into ``kwargs`` following
575
+ Pine's two numeric input overloads.
576
+
577
+ :param args: Positional arguments after ``defval`` and ``title``
578
+ :param kwargs: Keyword arguments; bound names are added in place
579
+ :raises TypeError: On too many positionals or a positional/keyword clash
580
+ """
581
+ if not args:
582
+ return
583
+ names = (cls._NUMERIC_OPTIONS_TAIL if isinstance(args[0], (tuple, list))
584
+ else cls._NUMERIC_RANGE_TAIL)
585
+ if len(args) > len(names):
586
+ raise TypeError("too many positional arguments for input")
587
+ for name, value in zip(names, args):
588
+ if name in kwargs:
589
+ raise TypeError(f"input got multiple values for argument '{name}'")
590
+ kwargs[name] = value
591
+
592
+ # noinspection PyMethodOverriding
593
+ @overload
594
+ @classmethod
595
+ def _int(cls, defval: int, title: str | None = None,
596
+ minval: int | None = None, maxval: int | None = None, step: int | None = None,
597
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
598
+ confirm: bool | None = False, display: _display.Display | None = None,
599
+ active: bool | None = None, *, _id: str = "") -> PyneInt: ...
600
+
601
+ # noinspection PyMethodOverriding
602
+ @overload
603
+ @classmethod
604
+ def _int(cls, defval: int, title: str | None = None,
605
+ options: tuple[int, ...] | None = None,
606
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
607
+ confirm: bool | None = False, display: _display.Display | None = None,
608
+ active: bool | None = None, *, _id: str = "") -> PyneInt: ...
609
+
610
+ @classmethod
611
+ def _int(cls, defval: int, title: str | None = None, *args,
612
+ _id: str = "", **kwargs) -> PyneInt:
613
+ """
614
+ Adds an input to your script's settings, which allows you to provide configuration options
615
+ to script users. This function adds a field for an integer input to the script's inputs.
616
+
617
+ Positional arguments after ``title`` follow Pine v6's two overloads
618
+ (``minval, maxval, step, ...`` or ``options, ...``); ``active`` is
619
+ UI-only in Pine and is accepted but ignored.
620
+
621
+ :param defval: The default value of the input
622
+ :param title: The title of the input
623
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
624
+ :return: The input value from toml file or the default
625
+ """
626
+ cls._bind_numeric_tail(args, kwargs)
627
+ inputs[_id] = InputData(
628
+ id=_id,
629
+ input_type='int',
630
+ defval=defval,
631
+ title=title,
632
+ minval=kwargs.get('minval'),
633
+ maxval=kwargs.get('maxval'),
634
+ step=kwargs.get('step'),
635
+ tooltip=kwargs.get('tooltip'),
636
+ inline=kwargs.get('inline'),
637
+ group=kwargs.get('group'),
638
+ confirm=kwargs.get('confirm', False),
639
+ options=kwargs.get('options'),
640
+ display=kwargs.get('display'),
641
+ )
642
+ return defval if _id not in _old_input_values else safe_convert.safe_int(_old_input_values[_id])
643
+
644
+ # noinspection PyUnusedLocal
645
+ @classmethod
646
+ def _bool(cls, defval: bool, title: str | None = None,
647
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
648
+ confirm: bool | None = False, display: _display.Display | None = None,
649
+ active: bool | None = None,
650
+ *, _id: str = "", **__) -> bool:
651
+ """
652
+ Adds an input to your script's settings, which allows you to provide configuration options
653
+ to script users. This function adds a field for a boolean input to the script's inputs.
654
+
655
+ :param defval: The default value of the input
656
+ :param title: The title of the input
657
+ :param tooltip: The tooltip of the input
658
+ :param inline: Inputs with the same inline string are displayed on one line
659
+ :param group: The group of the input
660
+ :param confirm: If True, the user will be asked to confirm the input
661
+ :param display: Controls where the script will display the input's information
662
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
663
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
664
+ :return: The input value from toml file or the default
665
+ """
666
+ inputs[_id] = InputData(
667
+ id=_id,
668
+ input_type='bool',
669
+ defval=defval,
670
+ title=title,
671
+ tooltip=tooltip,
672
+ inline=inline,
673
+ group=group,
674
+ confirm=confirm,
675
+ display=display,
676
+ )
677
+ return defval if _id not in _old_input_values else bool(_old_input_values[_id])
678
+
679
+ # noinspection PyMethodOverriding
680
+ @overload
681
+ @classmethod
682
+ def _float(cls, defval: float, title: str | None = None,
683
+ minval: float | None = None, maxval: float | None = None,
684
+ step: float | None = None,
685
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
686
+ confirm: bool | None = False, display: _display.Display | None = None,
687
+ active: bool | None = None, *, _id: str = "") -> PyneFloat: ...
688
+
689
+ # noinspection PyMethodOverriding
690
+ @overload
691
+ @classmethod
692
+ def _float(cls, defval: float, title: str | None = None,
693
+ options: tuple[int | float, ...] | None = None,
694
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
695
+ confirm: bool | None = False, display: _display.Display | None = None,
696
+ active: bool | None = None, *, _id: str = "") -> PyneFloat: ...
697
+
698
+ @classmethod
699
+ def _float(cls, defval: float, title: str | None = None, *args,
700
+ _id: str = "", **kwargs) -> PyneFloat:
701
+ """
702
+ Adds an input to your script's settings, which allows you to provide configuration options
703
+ to script users. This function adds a field for a float input to the script's inputs.
704
+
705
+ Positional arguments after ``title`` follow Pine v6's two overloads
706
+ (``minval, maxval, step, ...`` or ``options, ...``); ``active`` is
707
+ UI-only in Pine and is accepted but ignored.
708
+
709
+ :param defval: The default value of the input
710
+ :param title: The title of the input
711
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
712
+ :return: The input value from toml file or the default
713
+ """
714
+ cls._bind_numeric_tail(args, kwargs)
715
+ inputs[_id] = InputData(
716
+ id=_id,
717
+ input_type='float',
718
+ defval=defval,
719
+ title=title,
720
+ minval=kwargs.get('minval'),
721
+ maxval=kwargs.get('maxval'),
722
+ step=kwargs.get('step'),
723
+ tooltip=kwargs.get('tooltip'),
724
+ inline=kwargs.get('inline'),
725
+ group=kwargs.get('group'),
726
+ confirm=kwargs.get('confirm', False),
727
+ options=kwargs.get('options'),
728
+ display=kwargs.get('display'),
729
+ )
730
+ return defval if _id not in _old_input_values else safe_convert.safe_float(_old_input_values[_id])
731
+
732
+ # noinspection PyUnusedLocal
733
+ @classmethod
734
+ def string(cls, defval: str, title: str | None = None,
735
+ options: tuple[str, ...] | None = None,
736
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
737
+ confirm: bool | None = False,
738
+ display: _display.Display | None = None, active: bool | None = None,
739
+ *, _id: str = "", **__) -> str:
740
+ """
741
+ Adds an input to your script's settings, which allows you to provide configuration options
742
+ to script users. This function adds a field for a string input to the script's inputs.
743
+
744
+ :param defval: The default value of the input
745
+ :param title: The title of the input
746
+ :param tooltip: The tooltip of the input
747
+ :param inline: Inputs with the same inline string are displayed on one line
748
+ :param group: The group of the input
749
+ :param confirm: If True, the user will be asked to confirm the input
750
+ :param display: Controls where the script will display the input's information
751
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
752
+ :param options: A tuple of strings that the user can select from
753
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
754
+ :return: The input value from toml file or the default
755
+ """
756
+ inputs[_id] = InputData(
757
+ id=_id,
758
+ input_type='string',
759
+ defval=defval,
760
+ title=title,
761
+ tooltip=tooltip,
762
+ inline=inline,
763
+ group=group,
764
+ confirm=confirm,
765
+ display=display,
766
+ options=options,
767
+ )
768
+ return defval if _id not in _old_input_values else str(_old_input_values[_id])
769
+
770
+ # noinspection PyUnusedLocal
771
+ @classmethod
772
+ def color(cls, defval: Color, title: str | None = None,
773
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
774
+ confirm: bool | None = False, display: _display.Display | None = None,
775
+ active: bool | None = None,
776
+ *, _id: str = "", **__) -> Color:
777
+ """
778
+ Adds an input to your script's settings, which allows you to provide configuration options
779
+ to script users. This function adds a field for a color input to the script's inputs.
780
+
781
+ :param defval: The default value of the input
782
+ :param title: The title of the input
783
+ :param tooltip: The tooltip of the input
784
+ :param inline: Inputs with the same inline string are displayed on one line
785
+ :param group: The group of the input
786
+ :param confirm: If True, the user will be asked to confirm the input
787
+ :param display: Controls where the script will display the input's information
788
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
789
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
790
+ :return: The input value from toml file or the default
791
+ """
792
+ inputs[_id] = InputData(
793
+ id=_id,
794
+ input_type='color',
795
+ defval=defval,
796
+ title=title,
797
+ tooltip=tooltip,
798
+ inline=inline,
799
+ group=group,
800
+ confirm=confirm,
801
+ display=display,
802
+ )
803
+ return defval if _id not in _old_input_values else Color(_old_input_values[_id])
804
+
805
+ # noinspection PyUnusedLocal
806
+ @classmethod
807
+ def source(cls, defval: str | Source | float, title: str | None = None,
808
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
809
+ display: _display.Display | None = None, active: bool | None = None,
810
+ confirm: bool | None = False,
811
+ *, _id: str = "", **__) -> PyneFloat:
812
+ """
813
+ Adds an input to your script's settings, which allows you to provide configuration options
814
+ to script users. This function adds a field for a source input to the script's inputs.
815
+
816
+ Pine v6 positional order — uniquely among inputs, ``confirm`` comes LAST,
817
+ after ``display`` and ``active``.
818
+
819
+ :param defval: The name of the "source" registered in lib module,
820
+ like "open", "high", "low", "close", "hl2", "hlc3", "ohlc4"
821
+ :param title: The title of the input
822
+ :param tooltip: The tooltip of the input
823
+ :param inline: Inputs with the same inline string are displayed on one line
824
+ :param group: The group of the input
825
+ :param display: Controls where the script will display the input's information
826
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
827
+ :param confirm: If True, the user will be asked to confirm the input
828
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
829
+ :return: The input value from toml file or the default
830
+ """
831
+ defval = str(defval)
832
+ inputs[_id] = InputData(
833
+ id=_id,
834
+ input_type='source',
835
+ defval=defval,
836
+ title=title,
837
+ tooltip=tooltip,
838
+ inline=inline,
839
+ group=group,
840
+ confirm=confirm,
841
+ display=display,
842
+ )
843
+ # We actually return a string here, but the InputTransformer will add a `getattr()` call to get the
844
+ return defval if _id not in _old_input_values else _old_input_values[_id] # type: ignore[return-value]
845
+
846
+ # noinspection PyUnusedLocal
847
+ @classmethod
848
+ def enum(cls, defval: TEnum, title: str | None = None,
849
+ options: tuple[str, ...] | None = None,
850
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
851
+ confirm: bool | None = False,
852
+ display: _display.Display | None = None, active: bool | None = None,
853
+ *, _id: str = "", **__) -> TEnum:
854
+ """
855
+ Adds an input to your script's settings, which allows you to provide configuration options
856
+ to script users. This function adds a field for a enum input to the script's inputs.
857
+
858
+ :param defval: The default value of the input
859
+ :param title: The title of the input
860
+ :param tooltip: The tooltip of the input
861
+ :param inline: Inputs with the same inline string are displayed on one line
862
+ :param group: The group of the input
863
+ :param confirm: If True, the user will be asked to confirm the input
864
+ :param display: Controls where the script will display the input's information
865
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
866
+ :param options: A tuple of strings that the user can select from
867
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
868
+ :return: The input value from toml file or the default
869
+ """
870
+ inputs[_id] = InputData(
871
+ id=_id,
872
+ input_type='enum',
873
+ defval=defval,
874
+ title=title,
875
+ tooltip=tooltip,
876
+ inline=inline,
877
+ group=group,
878
+ confirm=confirm,
879
+ display=display,
880
+ options=options,
881
+ )
882
+ if _id not in _old_input_values:
883
+ return defval
884
+ else:
885
+ # Convert string value back to the specific enum type
886
+ value = _old_input_values[_id]
887
+ if isinstance(value, str):
888
+ try:
889
+ return defval.__class__(value)
890
+ except ValueError:
891
+ return defval
892
+ return defval
893
+
894
+ # We don't have interactive inputs, so price is stored as a float input; its
895
+ # Pine positional order has no minval/maxval/step, so it cannot alias _float
896
+ # noinspection PyUnusedLocal
897
+ @classmethod
898
+ def price(cls, defval: float, title: str | None = None,
899
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
900
+ confirm: bool | None = False, display: _display.Display | None = None,
901
+ active: bool | None = None,
902
+ *, _id: str = "", **__) -> PyneFloat:
903
+ """
904
+ Adds an input to your script's settings, which allows you to provide configuration options
905
+ to script users. This function adds a field for a price input to the script's inputs.
906
+
907
+ :param defval: The default value of the input
908
+ :param title: The title of the input
909
+ :param tooltip: The tooltip of the input
910
+ :param inline: Inputs with the same inline string are displayed on one line
911
+ :param group: The group of the input
912
+ :param confirm: If True, the user will be asked to confirm the input
913
+ :param display: Controls where the script will display the input's information
914
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
915
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
916
+ :return: The input value from toml file or the default
917
+ """
918
+ return cls._float(defval, title, tooltip=tooltip, inline=inline, group=group,
919
+ confirm=confirm, display=display, _id=_id)
920
+
921
+ # Pine's input.symbol has NO options: its third positional is tooltip, so it
922
+ # cannot alias string (whose third positional is options)
923
+ # noinspection PyUnusedLocal
924
+ @classmethod
925
+ def symbol(cls, defval: str, title: str | None = None,
926
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
927
+ confirm: bool | None = False, display: _display.Display | None = None,
928
+ active: bool | None = None,
929
+ *, _id: str = "", **__) -> str:
930
+ """
931
+ Adds an input to your script's settings, which allows you to provide configuration options
932
+ to script users. This function adds a field for a symbol input to the script's inputs.
933
+
934
+ :param defval: The default value of the input
935
+ :param title: The title of the input
936
+ :param tooltip: The tooltip of the input
937
+ :param inline: Inputs with the same inline string are displayed on one line
938
+ :param group: The group of the input
939
+ :param confirm: If True, the user will be asked to confirm the input
940
+ :param display: Controls where the script will display the input's information
941
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
942
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
943
+ :return: The input value from toml file or the default
944
+ """
945
+ return cls.string(defval, title, tooltip=tooltip, inline=inline, group=group,
946
+ confirm=confirm, display=display, _id=_id)
947
+
948
+ # Pine's input.text_area has neither options nor inline: its positional
949
+ # order is defval, title, tooltip, group, confirm, display, active
950
+ # noinspection PyUnusedLocal
951
+ @classmethod
952
+ def text_area(cls, defval: str, title: str | None = None,
953
+ tooltip: str | None = None, group: str | None = None,
954
+ confirm: bool | None = False, display: _display.Display | None = None,
955
+ active: bool | None = None,
956
+ *, _id: str = "", **__) -> str:
957
+ """
958
+ Adds an input to your script's settings, which allows you to provide configuration options
959
+ to script users. This function adds a field for a text area input to the script's inputs.
960
+
961
+ :param defval: The default value of the input
962
+ :param title: The title of the input
963
+ :param tooltip: The tooltip of the input
964
+ :param group: The group of the input
965
+ :param confirm: If True, the user will be asked to confirm the input
966
+ :param display: Controls where the script will display the input's information
967
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
968
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
969
+ :return: The input value from toml file or the default
970
+ """
971
+ return cls.string(defval, title, tooltip=tooltip, group=group,
972
+ confirm=confirm, display=display, _id=_id)
973
+
974
+ # time() returns UNIX timestamp in milliseconds (int); its Pine positional
975
+ # order has no minval/maxval/step, so it cannot alias _int
976
+ # noinspection PyUnusedLocal
977
+ @classmethod
978
+ def time(cls, defval: int, title: str | None = None,
979
+ tooltip: str | None = None, inline: str | None = None, group: str | None = None,
980
+ confirm: bool | None = False, display: _display.Display | None = None,
981
+ active: bool | None = None,
982
+ *, _id: str = "", **__) -> PyneInt:
983
+ """
984
+ Adds an input to your script's settings, which allows you to provide configuration options
985
+ to script users. This function adds a field for a time input to the script's inputs.
986
+
987
+ :param defval: The default value of the input (UNIX timestamp in milliseconds)
988
+ :param title: The title of the input
989
+ :param tooltip: The tooltip of the input
990
+ :param inline: Inputs with the same inline string are displayed on one line
991
+ :param group: The group of the input
992
+ :param confirm: If True, the user will be asked to confirm the input
993
+ :param display: Controls where the script will display the input's information
994
+ :param active: UI-only in Pine (greys out the field); accepted for parity, ignored
995
+ :param _id: The unique identifier of the input, it is filled by the InputTransformer
996
+ :return: The input value from toml file or the default
997
+ """
998
+ return cls._int(defval, title, tooltip=tooltip, inline=inline, group=group,
999
+ confirm=confirm, display=display, _id=_id)
1000
+
1001
+ int = _int
1002
+ bool = _bool
1003
+ float = _float
1004
+
1005
+ # These are incomplete, but good workaround
1006
+ session = string
1007
+ timeframe = string
1008
+
1009
+
1010
+ # noinspection PyShadowingBuiltins
1011
+ input = _Input()