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.
- opencode_pyneruntime-6.6.4.dist-info/METADATA +281 -0
- opencode_pyneruntime-6.6.4.dist-info/RECORD +261 -0
- opencode_pyneruntime-6.6.4.dist-info/WHEEL +5 -0
- opencode_pyneruntime-6.6.4.dist-info/entry_points.txt +6 -0
- opencode_pyneruntime-6.6.4.dist-info/licenses/LICENSE +201 -0
- opencode_pyneruntime-6.6.4.dist-info/licenses/NOTICE +21 -0
- opencode_pyneruntime-6.6.4.dist-info/top_level.txt +1 -0
- pynecore/__init__.py +6 -0
- pynecore/cli/__init__.py +2 -0
- pynecore/cli/app.py +238 -0
- pynecore/cli/commands/__init__.py +343 -0
- pynecore/cli/commands/benchmark.py +186 -0
- pynecore/cli/commands/compile.py +198 -0
- pynecore/cli/commands/data.py +857 -0
- pynecore/cli/commands/debug.py +63 -0
- pynecore/cli/commands/optimize.py +956 -0
- pynecore/cli/commands/plugin.py +242 -0
- pynecore/cli/commands/run.py +2006 -0
- pynecore/cli/pluggable.py +132 -0
- pynecore/cli/utils/__init__.py +0 -0
- pynecore/cli/utils/api_error_handler.py +168 -0
- pynecore/cli/utils/broker_picker.py +330 -0
- pynecore/cli/utils/error_hook.py +28 -0
- pynecore/cli/utils/keyreader.py +178 -0
- pynecore/cli/utils/provider_picker.py +19 -0
- pynecore/cli/utils/symbol_browser.py +1149 -0
- pynecore/core/__init__.py +0 -0
- pynecore/core/aggregator.py +257 -0
- pynecore/core/bar_magnifier.py +168 -0
- pynecore/core/broker/__init__.py +64 -0
- pynecore/core/broker/defaults.py +113 -0
- pynecore/core/broker/disappearance.py +927 -0
- pynecore/core/broker/emulator.py +345 -0
- pynecore/core/broker/exceptions.py +346 -0
- pynecore/core/broker/idempotency.py +401 -0
- pynecore/core/broker/intent_builder.py +334 -0
- pynecore/core/broker/journal.py +1785 -0
- pynecore/core/broker/models.py +1600 -0
- pynecore/core/broker/native_failsafe_manager.py +1436 -0
- pynecore/core/broker/one_way_emulator.py +1128 -0
- pynecore/core/broker/position.py +787 -0
- pynecore/core/broker/run_identity.py +126 -0
- pynecore/core/broker/software_entry_stop_engine.py +351 -0
- pynecore/core/broker/software_partial_bracket_engine.py +1379 -0
- pynecore/core/broker/spot_inventory.py +1327 -0
- pynecore/core/broker/storage.py +2655 -0
- pynecore/core/broker/store_helpers.py +2161 -0
- pynecore/core/broker/sync_engine.py +16070 -0
- pynecore/core/broker/validation.py +382 -0
- pynecore/core/class_property.py +7 -0
- pynecore/core/config.py +392 -0
- pynecore/core/csv_file.py +547 -0
- pynecore/core/currency.py +262 -0
- pynecore/core/data_converter.py +1002 -0
- pynecore/core/datetime.py +296 -0
- pynecore/core/download_info.py +71 -0
- pynecore/core/download_runner.py +274 -0
- pynecore/core/htf_aggregator.py +181 -0
- pynecore/core/import_hook.py +358 -0
- pynecore/core/instance_state.py +494 -0
- pynecore/core/live_ltf_collector.py +442 -0
- pynecore/core/live_ltf_window.py +189 -0
- pynecore/core/live_runner.py +1347 -0
- pynecore/core/module_property.py +26 -0
- pynecore/core/ohlcv_file.py +1888 -0
- pynecore/core/overload.py +371 -0
- pynecore/core/pine_cast.py +113 -0
- pynecore/core/pine_export.py +95 -0
- pynecore/core/pine_method.py +244 -0
- pynecore/core/pine_range.py +86 -0
- pynecore/core/pine_udt.py +69 -0
- pynecore/core/plugin/__init__.py +394 -0
- pynecore/core/plugin/broker.py +781 -0
- pynecore/core/plugin/cli.py +96 -0
- pynecore/core/plugin/live_provider.py +208 -0
- pynecore/core/plugin/provider.py +331 -0
- pynecore/core/provider_string.py +148 -0
- pynecore/core/random.py +40 -0
- pynecore/core/resampler.py +686 -0
- pynecore/core/safe_convert.py +64 -0
- pynecore/core/script.py +1011 -0
- pynecore/core/script_runner.py +3202 -0
- pynecore/core/security.py +1749 -0
- pynecore/core/security_process.py +1253 -0
- pynecore/core/security_shm.py +456 -0
- pynecore/core/series.py +417 -0
- pynecore/core/strategy_stats.py +669 -0
- pynecore/core/symbol_map.py +134 -0
- pynecore/core/syminfo.py +505 -0
- pynecore/core/viz.py +591 -0
- pynecore/lib/__init__.py +1771 -0
- pynecore/lib/_fixnan.py +32 -0
- pynecore/lib/_math_stateful.py +202 -0
- pynecore/lib/_timeframe_change.py +101 -0
- pynecore/lib/adjustment.py +6 -0
- pynecore/lib/alert.py +39 -0
- pynecore/lib/alert.pyi +14 -0
- pynecore/lib/array.py +1051 -0
- pynecore/lib/barmerge.py +60 -0
- pynecore/lib/barstate.py +30 -0
- pynecore/lib/box.py +415 -0
- pynecore/lib/chart.py +128 -0
- pynecore/lib/color.py +152 -0
- pynecore/lib/color.pyi +50 -0
- pynecore/lib/currency.py +62 -0
- pynecore/lib/dayofweek.py +36 -0
- pynecore/lib/dayofweek.pyi +18 -0
- pynecore/lib/display.py +8 -0
- pynecore/lib/dividends.py +9 -0
- pynecore/lib/earnings.py +11 -0
- pynecore/lib/extend.py +6 -0
- pynecore/lib/font.py +5 -0
- pynecore/lib/footprint.py +79 -0
- pynecore/lib/format.py +11 -0
- pynecore/lib/hline.py +67 -0
- pynecore/lib/hline.pyi +24 -0
- pynecore/lib/label.py +409 -0
- pynecore/lib/line.py +433 -0
- pynecore/lib/linefill.py +93 -0
- pynecore/lib/location.py +11 -0
- pynecore/lib/log.py +362 -0
- pynecore/lib/map.py +150 -0
- pynecore/lib/math.py +385 -0
- pynecore/lib/matrix.py +708 -0
- pynecore/lib/order.py +8 -0
- pynecore/lib/pivotpointtype.py +8 -0
- pynecore/lib/plot.py +95 -0
- pynecore/lib/plot.pyi +33 -0
- pynecore/lib/polyline.py +91 -0
- pynecore/lib/position.py +15 -0
- pynecore/lib/request.py +281 -0
- pynecore/lib/runtime.py +5 -0
- pynecore/lib/scale.py +9 -0
- pynecore/lib/session.py +267 -0
- pynecore/lib/session.pyi +12 -0
- pynecore/lib/shape.py +18 -0
- pynecore/lib/size.py +12 -0
- pynecore/lib/splits.py +4 -0
- pynecore/lib/strategy/__init__.py +4778 -0
- pynecore/lib/strategy/closedtrades.py +347 -0
- pynecore/lib/strategy/closedtrades.pyi +53 -0
- pynecore/lib/strategy/commission.py +9 -0
- pynecore/lib/strategy/direction.py +9 -0
- pynecore/lib/strategy/oca.py +13 -0
- pynecore/lib/strategy/opentrades.py +281 -0
- pynecore/lib/strategy/opentrades.pyi +49 -0
- pynecore/lib/strategy/risk.py +109 -0
- pynecore/lib/string.py +649 -0
- pynecore/lib/syminfo.py +84 -0
- pynecore/lib/ta.py +2230 -0
- pynecore/lib/table.py +290 -0
- pynecore/lib/text.py +17 -0
- pynecore/lib/ticker.py +207 -0
- pynecore/lib/timeframe.py +293 -0
- pynecore/lib/volume_row.py +67 -0
- pynecore/lib/xloc.py +4 -0
- pynecore/lib/yloc.py +5 -0
- pynecore/providers/__init__.py +0 -0
- pynecore/providers/ccxt.py +664 -0
- pynecore/providers/replay.py +187 -0
- pynecore/pynesys/__init__.py +0 -0
- pynecore/pynesys/api.py +498 -0
- pynecore/pynesys/compiler.py +112 -0
- pynecore/standalone.py +99 -0
- pynecore/testing/__init__.py +1 -0
- pynecore/testing/broker_lab/__init__.py +41 -0
- pynecore/testing/broker_lab/__main__.py +5 -0
- pynecore/testing/broker_lab/cli.py +87 -0
- pynecore/testing/broker_lab/generate.py +47 -0
- pynecore/testing/broker_lab/model.py +84 -0
- pynecore/testing/broker_lab/reference.py +645 -0
- pynecore/testing/broker_lab/runner.py +372 -0
- pynecore/testing/broker_lab/scheduler.py +50 -0
- pynecore/testing/broker_lab/subprocess.py +73 -0
- pynecore/transformers/__init__.py +0 -0
- pynecore/transformers/builtin_shadow.py +136 -0
- pynecore/transformers/closure_arguments_transformer.py +428 -0
- pynecore/transformers/display_rewrite.py +140 -0
- pynecore/transformers/dynamic_default.py +147 -0
- pynecore/transformers/function_isolation.py +757 -0
- pynecore/transformers/import_lifter.py +61 -0
- pynecore/transformers/import_normalizer.py +328 -0
- pynecore/transformers/inline_series_hoist.py +178 -0
- pynecore/transformers/input_transformer.py +175 -0
- pynecore/transformers/lib_series.py +201 -0
- pynecore/transformers/locations.py +70 -0
- pynecore/transformers/module_properties.json +3387 -0
- pynecore/transformers/module_property.py +221 -0
- pynecore/transformers/ne_guard.py +70 -0
- pynecore/transformers/persistent.py +320 -0
- pynecore/transformers/persistent_series.py +76 -0
- pynecore/transformers/safe_convert_transformer.py +97 -0
- pynecore/transformers/safe_division_transformer.py +95 -0
- pynecore/transformers/script_requirements.py +308 -0
- pynecore/transformers/security.py +752 -0
- pynecore/transformers/security_instantiation.py +274 -0
- pynecore/transformers/series.py +275 -0
- pynecore/transformers/slot_layout.py +381 -0
- pynecore/transformers/type_checking_stripper.py +25 -0
- pynecore/transformers/unused_series_detector.py +267 -0
- pynecore/types/__init__.py +21 -0
- pynecore/types/alert.py +5 -0
- pynecore/types/barmerge.py +5 -0
- pynecore/types/base.py +39 -0
- pynecore/types/box.py +37 -0
- pynecore/types/chart.py +17 -0
- pynecore/types/color.py +107 -0
- pynecore/types/currency.py +5 -0
- pynecore/types/datetime.py +6 -0
- pynecore/types/display.py +5 -0
- pynecore/types/dividends.py +5 -0
- pynecore/types/earnings.py +5 -0
- pynecore/types/extend.py +5 -0
- pynecore/types/font.py +5 -0
- pynecore/types/footprint.py +41 -0
- pynecore/types/format.py +5 -0
- pynecore/types/hline.py +24 -0
- pynecore/types/ib_persistent.py +8 -0
- pynecore/types/ib_persistent.pyi +10 -0
- pynecore/types/label.py +35 -0
- pynecore/types/line.py +32 -0
- pynecore/types/linefill.py +13 -0
- pynecore/types/location.py +5 -0
- pynecore/types/matrix.py +999 -0
- pynecore/types/na.py +237 -0
- pynecore/types/na.pyi +83 -0
- pynecore/types/ohlcv.py +12 -0
- pynecore/types/order.py +5 -0
- pynecore/types/persistent.py +8 -0
- pynecore/types/persistent.pyi +13 -0
- pynecore/types/pine_types.py +11 -0
- pynecore/types/pine_types.pyi +15 -0
- pynecore/types/pivotpointtype.py +5 -0
- pynecore/types/plot.py +12 -0
- pynecore/types/plot_meta.py +60 -0
- pynecore/types/polyline.py +40 -0
- pynecore/types/position.py +5 -0
- pynecore/types/scale.py +5 -0
- pynecore/types/script_type.py +15 -0
- pynecore/types/series.py +23 -0
- pynecore/types/series.pyi +19 -0
- pynecore/types/session.py +35 -0
- pynecore/types/shape.py +5 -0
- pynecore/types/size.py +5 -0
- pynecore/types/source.py +33 -0
- pynecore/types/splits.py +5 -0
- pynecore/types/strategy.py +45 -0
- pynecore/types/table.py +87 -0
- pynecore/types/text.py +13 -0
- pynecore/types/type_checker.py +7 -0
- pynecore/types/type_checker.pyi +48 -0
- pynecore/types/volume_row.py +36 -0
- pynecore/types/weekdays.py +11 -0
- pynecore/types/xloc.py +5 -0
- pynecore/types/yloc.py +5 -0
- pynecore/utils/__init__.py +0 -0
- pynecore/utils/file_utils.py +50 -0
- pynecore/utils/rich/__init__.py +0 -0
- pynecore/utils/rich/date_column.py +25 -0
- pynecore/utils/sequence_view.py +92 -0
- pynecore/utils/stdlib_checker.py +17 -0
pynecore/lib/math.py
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
from typing import TypeVar, cast, overload
|
|
2
|
+
import builtins
|
|
3
|
+
import math
|
|
4
|
+
from decimal import Decimal, ROUND_HALF_UP, localcontext
|
|
5
|
+
|
|
6
|
+
from ..types.na import NA, na_float
|
|
7
|
+
from ..types import PyneFloat, PyneInt
|
|
8
|
+
|
|
9
|
+
from . import syminfo
|
|
10
|
+
from ._math_stateful import random, sum
|
|
11
|
+
|
|
12
|
+
TFI = TypeVar('TFI', float, int)
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
'e', 'pi', 'phi', 'rphi',
|
|
16
|
+
'abs', 'acos', 'asin', 'atan', 'avg', 'ceil', 'cos', 'exp', 'floor',
|
|
17
|
+
'log', 'log10', 'max', 'min', 'pow', 'random', 'round', 'round_to_mintick',
|
|
18
|
+
'sign', 'sin', 'sqrt', 'sum', 'tan', 'todegrees', 'toradians'
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
# Constants
|
|
22
|
+
e = math.e
|
|
23
|
+
pi = math.pi
|
|
24
|
+
phi = (1 + math.sqrt(5)) / 2
|
|
25
|
+
rphi = 1 / phi
|
|
26
|
+
|
|
27
|
+
# noinspection PyShadowingBuiltins
|
|
28
|
+
def abs(number: TFI | NA[TFI]) -> PyneFloat:
|
|
29
|
+
"""
|
|
30
|
+
Returns the absolute value of a number.
|
|
31
|
+
|
|
32
|
+
:param number: A number.
|
|
33
|
+
:return: The absolute value of the number.
|
|
34
|
+
"""
|
|
35
|
+
if (isinstance(number, NA) or number != number):
|
|
36
|
+
return na_float
|
|
37
|
+
return builtins.abs(number)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def acos(value: TFI | NA[TFI]) -> PyneFloat:
|
|
41
|
+
"""
|
|
42
|
+
Returns the arc cosine of a value.
|
|
43
|
+
|
|
44
|
+
:param value: A value.
|
|
45
|
+
:return: The arc cosine of the value.
|
|
46
|
+
"""
|
|
47
|
+
if (isinstance(value, NA) or value != value):
|
|
48
|
+
return na_float
|
|
49
|
+
return math.acos(value)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def asin(value: TFI | NA[TFI]) -> PyneFloat:
|
|
53
|
+
"""
|
|
54
|
+
Returns the arc sine of a value.
|
|
55
|
+
|
|
56
|
+
:param value: A value.
|
|
57
|
+
:return: The arc sine of the value.
|
|
58
|
+
"""
|
|
59
|
+
if (isinstance(value, NA) or value != value):
|
|
60
|
+
return na_float
|
|
61
|
+
return math.asin(value)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def atan(value: TFI | NA[TFI]) -> PyneFloat:
|
|
65
|
+
"""
|
|
66
|
+
Returns the arc tangent of a value.
|
|
67
|
+
|
|
68
|
+
:param value: A value.
|
|
69
|
+
:return: The arc tangent of the value.
|
|
70
|
+
"""
|
|
71
|
+
if (isinstance(value, NA) or value != value):
|
|
72
|
+
return na_float
|
|
73
|
+
return math.atan(value)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def avg(*numbers: TFI | NA[TFI]) -> PyneFloat:
|
|
77
|
+
"""
|
|
78
|
+
Returns the average of the numbers.
|
|
79
|
+
|
|
80
|
+
:param numbers: Numbers.
|
|
81
|
+
:return: The average of the numbers.
|
|
82
|
+
"""
|
|
83
|
+
assert numbers, "At least one number is necessary!"
|
|
84
|
+
|
|
85
|
+
if any((isinstance(n, NA) or n != n) for n in numbers):
|
|
86
|
+
return na_float
|
|
87
|
+
|
|
88
|
+
return builtins.sum(n for n in numbers) / len(numbers)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def ceil(number: TFI | NA[TFI]) -> PyneInt:
|
|
92
|
+
"""
|
|
93
|
+
Returns the smallest integer greater than or equal to a number.
|
|
94
|
+
|
|
95
|
+
:param number: A number.
|
|
96
|
+
:return: The smallest integer greater than or equal to the number.
|
|
97
|
+
"""
|
|
98
|
+
if (isinstance(number, NA) or number != number):
|
|
99
|
+
return NA(int)
|
|
100
|
+
return math.ceil(number)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def cos(angle: TFI | NA[TFI]) -> PyneFloat:
|
|
104
|
+
"""
|
|
105
|
+
Returns the cosine of an angle.
|
|
106
|
+
|
|
107
|
+
:param angle: An angle in radians.
|
|
108
|
+
:return: The cosine of the angle.
|
|
109
|
+
"""
|
|
110
|
+
if (isinstance(angle, NA) or angle != angle):
|
|
111
|
+
return na_float
|
|
112
|
+
return math.cos(angle)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def exp(number: TFI | NA[TFI]) -> PyneFloat:
|
|
116
|
+
"""
|
|
117
|
+
Returns e raised to the power of a number.
|
|
118
|
+
|
|
119
|
+
:param number: A number.
|
|
120
|
+
:return: e raised to the power of the number.
|
|
121
|
+
"""
|
|
122
|
+
if (isinstance(number, NA) or number != number):
|
|
123
|
+
return na_float
|
|
124
|
+
return math.exp(number)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def floor(number: TFI | NA[TFI]) -> PyneInt:
|
|
128
|
+
"""
|
|
129
|
+
Returns the largest integer less than or equal to a number.
|
|
130
|
+
|
|
131
|
+
:param number: A number.
|
|
132
|
+
:return: The largest integer less than or equal to the number.
|
|
133
|
+
"""
|
|
134
|
+
if (isinstance(number, NA) or number != number):
|
|
135
|
+
return NA(int)
|
|
136
|
+
# int() truncates toward zero; Pine's floor is a true floor (floor(-1.2) == -2)
|
|
137
|
+
return math.floor(number)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def log(number: TFI | NA[TFI]) -> PyneFloat:
|
|
141
|
+
"""
|
|
142
|
+
Returns the natural logarithm of a number.
|
|
143
|
+
|
|
144
|
+
:param number: A number.
|
|
145
|
+
:return: The natural logarithm of the number.
|
|
146
|
+
"""
|
|
147
|
+
if (isinstance(number, NA) or number != number):
|
|
148
|
+
return na_float
|
|
149
|
+
return math.log(number)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def log10(number: TFI | NA[TFI]) -> PyneFloat:
|
|
153
|
+
"""
|
|
154
|
+
Returns the base-10 logarithm of a number.
|
|
155
|
+
|
|
156
|
+
:param number: A number.
|
|
157
|
+
:return: The base-10 logarithm of the number.
|
|
158
|
+
"""
|
|
159
|
+
if (isinstance(number, NA) or number != number):
|
|
160
|
+
return na_float
|
|
161
|
+
return math.log10(number)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _na_of_operands(numbers: tuple[TFI | NA[TFI], ...]) -> PyneFloat:
|
|
165
|
+
"""
|
|
166
|
+
Return the na matching the operands' numeric contract: na_float when any
|
|
167
|
+
type-carrying operand is float-like, NA(int) when the type-carrying operands
|
|
168
|
+
are all int-like, the typeless na when no operand carries a type at all.
|
|
169
|
+
Typeless na operands are neutral — they must not push an int contract to float.
|
|
170
|
+
"""
|
|
171
|
+
saw_typed = False
|
|
172
|
+
for n in numbers:
|
|
173
|
+
if n != n:
|
|
174
|
+
# A native nan is a float-typed na by definition
|
|
175
|
+
return na_float
|
|
176
|
+
if isinstance(n, NA):
|
|
177
|
+
if n.type is None:
|
|
178
|
+
continue
|
|
179
|
+
saw_typed = True
|
|
180
|
+
if n.type is not int:
|
|
181
|
+
return na_float
|
|
182
|
+
else:
|
|
183
|
+
saw_typed = True
|
|
184
|
+
if not isinstance(n, int):
|
|
185
|
+
return na_float
|
|
186
|
+
return NA(int) if saw_typed else NA(None)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# noinspection PyShadowingBuiltins
|
|
190
|
+
@overload
|
|
191
|
+
def max(*numbers: int) -> PyneInt: ...
|
|
192
|
+
# noinspection PyShadowingBuiltins
|
|
193
|
+
@overload
|
|
194
|
+
def max(*numbers: TFI | NA[TFI]) -> PyneFloat: ...
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# noinspection PyShadowingBuiltins
|
|
198
|
+
def max(*numbers: TFI | NA[TFI]) -> PyneFloat:
|
|
199
|
+
"""
|
|
200
|
+
Returns the largest number.
|
|
201
|
+
|
|
202
|
+
:param numbers: Numbers.
|
|
203
|
+
:return: The largest number.
|
|
204
|
+
"""
|
|
205
|
+
assert numbers, "At least one number is necessary!"
|
|
206
|
+
|
|
207
|
+
if any((isinstance(n, NA) or n != n) for n in numbers):
|
|
208
|
+
return _na_of_operands(numbers)
|
|
209
|
+
|
|
210
|
+
return builtins.max(cast(list[TFI], numbers))
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
# noinspection PyShadowingBuiltins
|
|
214
|
+
@overload
|
|
215
|
+
def min(*numbers: int) -> PyneInt: ...
|
|
216
|
+
# noinspection PyShadowingBuiltins
|
|
217
|
+
@overload
|
|
218
|
+
def min(*numbers: TFI | NA[TFI]) -> PyneFloat: ...
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
# noinspection PyShadowingBuiltins
|
|
222
|
+
def min(*numbers: TFI | NA[TFI]) -> PyneFloat:
|
|
223
|
+
"""
|
|
224
|
+
Returns the smallest number.
|
|
225
|
+
|
|
226
|
+
:param numbers: Numbers.
|
|
227
|
+
:return: The smallest number.
|
|
228
|
+
"""
|
|
229
|
+
assert numbers, "At least one number is necessary!"
|
|
230
|
+
|
|
231
|
+
if any((isinstance(n, NA) or n != n) for n in numbers):
|
|
232
|
+
return _na_of_operands(numbers)
|
|
233
|
+
|
|
234
|
+
return builtins.min(cast(list[TFI], numbers))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# noinspection PyShadowingBuiltins
|
|
238
|
+
def pow(base: TFI | NA[TFI], exponent: TFI | NA[TFI]) -> PyneFloat:
|
|
239
|
+
"""
|
|
240
|
+
Returns a number raised to the power of another number.
|
|
241
|
+
|
|
242
|
+
:param base: The base number.
|
|
243
|
+
:param exponent: The exponent number.
|
|
244
|
+
:return: The base number raised to the power of the exponent number.
|
|
245
|
+
"""
|
|
246
|
+
if (isinstance(base, NA) or base != base) or (isinstance(exponent, NA) or exponent != exponent):
|
|
247
|
+
return na_float
|
|
248
|
+
|
|
249
|
+
return base ** exponent
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# noinspection PyShadowingBuiltins
|
|
253
|
+
@overload
|
|
254
|
+
def round(number: TFI | NA[TFI]) -> PyneInt: ...
|
|
255
|
+
# noinspection PyShadowingBuiltins
|
|
256
|
+
@overload
|
|
257
|
+
def round(number: TFI | NA[TFI], precision: PyneInt) -> PyneFloat: ...
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
# noinspection PyShadowingBuiltins
|
|
261
|
+
def round(number: TFI | NA[TFI], precision: PyneInt = NA(int)) -> PyneFloat:
|
|
262
|
+
"""
|
|
263
|
+
Returns a number rounded to a specified number of decimal places.
|
|
264
|
+
|
|
265
|
+
:param number: A number.
|
|
266
|
+
:param precision: The number of decimal places to round to.
|
|
267
|
+
:return: The rounded number.
|
|
268
|
+
"""
|
|
269
|
+
if (isinstance(number, NA) or number != number):
|
|
270
|
+
# No precision means the int contract (first overload), so an int-typed na
|
|
271
|
+
return na_float if isinstance(precision, int) else NA(int)
|
|
272
|
+
# TV-measured: ties round away from zero on the decimal (shortest-repr) value,
|
|
273
|
+
# not half-even on the binary double (round(2.5) == 3, round(-2.5) == -3,
|
|
274
|
+
# round(2.675, 2) == 2.68 — builtins.round gives 2, -2 and 2.67 there)
|
|
275
|
+
if not math.isfinite(number):
|
|
276
|
+
# Pine has no non-finite values (1/0 is na); the precision overload keeps
|
|
277
|
+
# builtins.round() behavior (returns the float unchanged), but the
|
|
278
|
+
# one-argument overload must honor its int contract, so it yields an int na
|
|
279
|
+
return number if isinstance(precision, int) else NA(int)
|
|
280
|
+
decimal_number = Decimal(repr(number))
|
|
281
|
+
if not isinstance(precision, int):
|
|
282
|
+
return int(decimal_number.to_integral_value(rounding=ROUND_HALF_UP))
|
|
283
|
+
# quantize() fails when the result needs more digits than the context precision
|
|
284
|
+
# (default 28), so size a local context from the magnitude and the requested
|
|
285
|
+
# precision (e.g. round(1e30, 2), round(x, 100))
|
|
286
|
+
with localcontext() as ctx:
|
|
287
|
+
ctx.prec = builtins.max(1, decimal_number.adjusted() + precision + 2)
|
|
288
|
+
return float(decimal_number.quantize(Decimal(1).scaleb(-precision),
|
|
289
|
+
rounding=ROUND_HALF_UP))
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
@overload
|
|
293
|
+
def round_to_mintick(number: float | int) -> float: ...
|
|
294
|
+
@overload
|
|
295
|
+
def round_to_mintick(number: PyneFloat | PyneInt) -> PyneFloat: ...
|
|
296
|
+
|
|
297
|
+
def round_to_mintick(number: PyneFloat | PyneInt) -> PyneFloat:
|
|
298
|
+
"""
|
|
299
|
+
Returns value rounded to symbol's mintick with ties rounding up.
|
|
300
|
+
"""
|
|
301
|
+
if (isinstance(number, NA) or number != number):
|
|
302
|
+
return na_float
|
|
303
|
+
# `mintick = minmove / pricescale` (Pine syminfo). Reconstruct via int math so
|
|
304
|
+
# `minmove=1` paths stay bit-identical to the old formula, while `minmove != 1`
|
|
305
|
+
# symbols (e.g. QM1!: mintick=0.025, pricescale=1000, minmove=25) round correctly.
|
|
306
|
+
return int(number / syminfo.mintick + 0.5) * syminfo.minmove / syminfo.pricescale
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def sign(number: TFI | NA[TFI]) -> PyneFloat:
|
|
310
|
+
"""
|
|
311
|
+
Returns the sign of a number.
|
|
312
|
+
|
|
313
|
+
:param number: A number.
|
|
314
|
+
:return: The sign of the number.
|
|
315
|
+
"""
|
|
316
|
+
if (isinstance(number, NA) or number != number):
|
|
317
|
+
return na_float
|
|
318
|
+
if number == 0.0:
|
|
319
|
+
return 0.0
|
|
320
|
+
if number > 0.0:
|
|
321
|
+
return 1.0
|
|
322
|
+
return -1.0
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def sin(angle: float | int | NA) -> PyneFloat:
|
|
326
|
+
"""
|
|
327
|
+
Returns the sine of an angle.
|
|
328
|
+
|
|
329
|
+
:param angle: An angle in radians.
|
|
330
|
+
:return: The sine of the angle.
|
|
331
|
+
"""
|
|
332
|
+
if (isinstance(angle, NA) or angle != angle):
|
|
333
|
+
return na_float
|
|
334
|
+
return math.sin(angle)
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def sqrt(number: float | int | NA) -> PyneFloat:
|
|
338
|
+
"""
|
|
339
|
+
Returns the square root of a number.
|
|
340
|
+
|
|
341
|
+
:param number: A number.
|
|
342
|
+
:return: The square root of the number.
|
|
343
|
+
"""
|
|
344
|
+
if (isinstance(number, NA) or number != number):
|
|
345
|
+
return na_float
|
|
346
|
+
try:
|
|
347
|
+
return math.sqrt(number)
|
|
348
|
+
except ValueError:
|
|
349
|
+
return na_float
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def tan(angle: TFI | NA[TFI]) -> PyneFloat:
|
|
353
|
+
"""
|
|
354
|
+
Returns the tangent of an angle.
|
|
355
|
+
|
|
356
|
+
:param angle: An angle in radians.
|
|
357
|
+
:return: The tangent of the angle.
|
|
358
|
+
"""
|
|
359
|
+
if (isinstance(angle, NA) or angle != angle):
|
|
360
|
+
return na_float
|
|
361
|
+
return math.tan(angle)
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def todegrees(angle: TFI | NA[TFI]) -> PyneFloat:
|
|
365
|
+
"""
|
|
366
|
+
Converts an angle from radians to degrees.
|
|
367
|
+
|
|
368
|
+
:param angle: An angle in radians.
|
|
369
|
+
:return: The angle in degrees.
|
|
370
|
+
"""
|
|
371
|
+
if (isinstance(angle, NA) or angle != angle):
|
|
372
|
+
return na_float
|
|
373
|
+
return math.degrees(angle)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def toradians(angle: TFI | NA[TFI]) -> PyneFloat:
|
|
377
|
+
"""
|
|
378
|
+
Converts an angle from degrees to radians.
|
|
379
|
+
|
|
380
|
+
:param angle: An angle in degrees.
|
|
381
|
+
:return: The angle in radians.
|
|
382
|
+
"""
|
|
383
|
+
if (isinstance(angle, NA) or angle != angle):
|
|
384
|
+
return na_float
|
|
385
|
+
return math.radians(angle)
|