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/barmerge.py
ADDED
|
@@ -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()
|
pynecore/lib/barstate.py
ADDED
|
@@ -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()
|