BinaryOptionsToolsV2 0.2.12__tar.gz → 0.2.13__tar.gz
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.
Potentially problematic release.
This version of BinaryOptionsToolsV2 might be problematic. Click here for more details.
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/config.py +12 -5
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/pocketoption/asynchronous.py +259 -21
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/pocketoption/synchronous.py +131 -21
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/Cargo.lock +247 -229
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/Cargo.toml +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/PKG-INFO +34 -40
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/README.md +26 -33
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/Cargo.toml +8 -6
- {binaryoptionstoolsv2-0.2.12/crates/macros → binaryoptionstoolsv2-0.2.13/crates/binary_options_tools}/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/Readme.md +1 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/config.rs +13 -6
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/modules/profile.rs +5 -3
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/types.rs +1 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/candle.rs +1 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/connect.rs +10 -8
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/deals.rs +3 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/get_candles.rs +34 -3
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/historical_data.rs +12 -4
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/keep_alive.rs +2 -6
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/pending_trades_tests.rs +7 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/subscriptions.rs +1 -28
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/pocket_client.rs +46 -8
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/state.rs +55 -11
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/utils.rs +342 -41
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/Cargo.toml +6 -6
- {binaryoptionstoolsv2-0.2.12/crates/binary_options_tools → binaryoptionstoolsv2-0.2.13/crates/bindings_pyo3}/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/Readme.md +20 -34
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/build.rs +11 -1
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/config.rs +55 -4
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/pocketoption.rs +33 -4
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/Cargo.toml +5 -5
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/Cargo.toml +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/client.rs +5 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/signals.rs +10 -6
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/Cargo.toml +4 -4
- {binaryoptionstoolsv2-0.2.12/crates/bindings_pyo3 → binaryoptionstoolsv2-0.2.13/crates/macros}/LICENSE +2 -2
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/pyproject.toml +7 -7
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/BinaryOptionsToolsV2.pyi +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/__init__.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/pocketoption/__init__.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/pocketoption/tools/__init__.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/pocketoption/tools/login.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/tracing.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/BinaryOptionsToolsV2/validator.py +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/data/expert_options_regions.json +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/data/pocket_options_regions.json +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/error.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/action.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/client.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/connect.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/error.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/modules/keep_alive.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/modules/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/regions.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/expertoptions/state.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/framework/market.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/framework/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/framework/virtual_market.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/lib.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/error.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/assets.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/balance.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/deals_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/pending_trades.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/raw.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/resilient_parsing_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/server_time.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/trades.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/trades_tests/common.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/trades_tests/concurrency.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/modules/trades_tests/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/regions.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/ssid.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/pocketoption/types.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/traits.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/utils/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/utils/serialize.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/binary_options_tools/src/validator.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/error.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/framework.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/lib.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/logs.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/runtime.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/stream.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/bindings_pyo3/src/validator.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/.gitignore +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/README.md +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/diagrams/architecture.txt +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/diagrams/diagram.txt +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/docs/testing-framework.md +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/examples/echo_client.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/examples/middleware_example.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/examples/testing_echo_client.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/src/lib.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/src/modules/lightweight.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/src/modules/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/macros/src/rule.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/builder.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/callback.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/connector.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/error.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/lib.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/message.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/middleware.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/reimports.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/rules.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/statistics.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/testing.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/traits.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/utils/mod.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/utils/stream.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/utils/time.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/src/utils/tracing.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/middleware_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/rule_macro_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/runner_command_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/stream_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/testing_wrapper_tests.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/core/tests/two_step_standalone.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/.gitignore +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/ActionImpl_README.md +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/Cargo.lock +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/src/action.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/src/lib.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/src/region.rs +0 -0
- {binaryoptionstoolsv2-0.2.12 → binaryoptionstoolsv2-0.2.13}/crates/macros/src/timeout.rs +0 -0
|
@@ -27,7 +27,12 @@ class Config:
|
|
|
27
27
|
connection_initialization_timeout_secs: int = 60
|
|
28
28
|
timeout_secs: int = 30
|
|
29
29
|
urls: List[str] = field(default_factory=list)
|
|
30
|
-
|
|
30
|
+
proxy: str = None
|
|
31
|
+
user_agent: str = None
|
|
32
|
+
origin: str = None
|
|
33
|
+
sec_websocket_extensions: str = None
|
|
34
|
+
tls_cipher_suites: List[str] = None
|
|
35
|
+
tls_alpn: List[str] = None
|
|
31
36
|
|
|
32
37
|
# Logging configuration
|
|
33
38
|
terminal_logging: bool = False
|
|
@@ -67,7 +72,12 @@ class Config:
|
|
|
67
72
|
self._pyconfig.connection_initialization_timeout_secs = self.connection_initialization_timeout_secs
|
|
68
73
|
self._pyconfig.timeout_secs = self.timeout_secs
|
|
69
74
|
self._pyconfig.urls = self.urls
|
|
70
|
-
self._pyconfig.
|
|
75
|
+
self._pyconfig.proxy = self.proxy
|
|
76
|
+
self._pyconfig.user_agent = self.user_agent
|
|
77
|
+
self._pyconfig.origin = self.origin
|
|
78
|
+
self._pyconfig.sec_websocket_extensions = self.sec_websocket_extensions
|
|
79
|
+
self._pyconfig.tls_cipher_suites = self.tls_cipher_suites
|
|
80
|
+
self._pyconfig.tls_alpn = self.tls_alpn
|
|
71
81
|
|
|
72
82
|
def _validate(self):
|
|
73
83
|
"""Validate config values, raising ValueError on invalid input."""
|
|
@@ -81,8 +91,6 @@ class Config:
|
|
|
81
91
|
raise ValueError("connection_initialization_timeout_secs must be at least 1")
|
|
82
92
|
if self.timeout_secs < 1:
|
|
83
93
|
raise ValueError("timeout_secs must be at least 1")
|
|
84
|
-
if self.max_subscriptions < 1:
|
|
85
|
-
raise ValueError("max_subscriptions must be at least 1")
|
|
86
94
|
|
|
87
95
|
@classmethod
|
|
88
96
|
def from_dict(cls, config_dict: Dict[str, Any]) -> "Config":
|
|
@@ -105,7 +113,6 @@ class Config:
|
|
|
105
113
|
"connection_initialization_timeout_secs": self.connection_initialization_timeout_secs,
|
|
106
114
|
"timeout_secs": self.timeout_secs,
|
|
107
115
|
"urls": self.urls,
|
|
108
|
-
"max_subscriptions": self.max_subscriptions,
|
|
109
116
|
"terminal_logging": self.terminal_logging,
|
|
110
117
|
"log_level": self.log_level,
|
|
111
118
|
"extra_duration": self.extra_duration,
|
|
@@ -2,8 +2,11 @@ import asyncio
|
|
|
2
2
|
import json
|
|
3
3
|
import re
|
|
4
4
|
import sys
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import time
|
|
6
|
+
import warnings
|
|
7
|
+
from collections import deque
|
|
8
|
+
from datetime import datetime, timezone, timedelta
|
|
9
|
+
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union, AsyncGenerator
|
|
7
10
|
|
|
8
11
|
from ..config import Config
|
|
9
12
|
from ..validator import Validator
|
|
@@ -30,6 +33,18 @@ class AsyncSubscription:
|
|
|
30
33
|
return json.loads(await anext(self.subscription))
|
|
31
34
|
|
|
32
35
|
|
|
36
|
+
class AsyncRawSubscription:
|
|
37
|
+
def __init__(self, subscription):
|
|
38
|
+
"""Asynchronous Iterator over raw message strings"""
|
|
39
|
+
self.subscription = subscription
|
|
40
|
+
|
|
41
|
+
def __aiter__(self):
|
|
42
|
+
return self
|
|
43
|
+
|
|
44
|
+
async def __anext__(self):
|
|
45
|
+
return await anext(self.subscription)
|
|
46
|
+
|
|
47
|
+
|
|
33
48
|
class RawHandler:
|
|
34
49
|
"""
|
|
35
50
|
Handler for advanced raw WebSocket message operations.
|
|
@@ -453,9 +468,23 @@ class PocketOptionAsync:
|
|
|
453
468
|
- high: Highest price
|
|
454
469
|
- low: Lowest price
|
|
455
470
|
- close: Closing price
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
471
|
+
|
|
472
|
+
Note:
|
|
473
|
+
WARNING: This function only fetches closed historical candles and is intended
|
|
474
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
475
|
+
for real-time/live trading as it does not include the current forming candle
|
|
476
|
+
and can introduce gaps if called sequentially during live trading.
|
|
477
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
478
|
+
"""
|
|
479
|
+
warnings.warn(
|
|
480
|
+
"candles() is deprecated and will be removed in a new release. "
|
|
481
|
+
"Please use get_candles_live() for live gap-free candles instead.",
|
|
482
|
+
DeprecationWarning,
|
|
483
|
+
stacklevel=2,
|
|
484
|
+
)
|
|
485
|
+
gen = self.get_candles_live(asset, period, hours=2.0)
|
|
486
|
+
closed, forming = await anext(gen)
|
|
487
|
+
return closed
|
|
459
488
|
|
|
460
489
|
async def get_candles(self, asset: str, period: int, offset: int) -> List[Dict]:
|
|
461
490
|
"""
|
|
@@ -475,11 +504,24 @@ class PocketOptionAsync:
|
|
|
475
504
|
- close: Closing price
|
|
476
505
|
|
|
477
506
|
Note:
|
|
478
|
-
Available timeframes: 1, 5, 15, 30, 60, 300 seconds
|
|
479
|
-
Maximum period depends on the timeframe
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
507
|
+
- Available timeframes: 1, 5, 15, 30, 60, 300 seconds
|
|
508
|
+
- Maximum period depends on the timeframe
|
|
509
|
+
- WARNING: This function only fetches closed historical candles and is intended
|
|
510
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
511
|
+
for real-time/live trading as it does not include the current forming candle
|
|
512
|
+
and can introduce gaps if called sequentially during live trading.
|
|
513
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
514
|
+
"""
|
|
515
|
+
warnings.warn(
|
|
516
|
+
"get_candles() is deprecated and will be removed in a new release. "
|
|
517
|
+
"Please use get_candles_live() for live gap-free candles instead.",
|
|
518
|
+
DeprecationWarning,
|
|
519
|
+
stacklevel=2,
|
|
520
|
+
)
|
|
521
|
+
hours = max(0.1, offset / 3600.0)
|
|
522
|
+
gen = self.get_candles_live(asset, period, hours=hours)
|
|
523
|
+
closed, forming = await anext(gen)
|
|
524
|
+
return closed
|
|
483
525
|
|
|
484
526
|
async def get_candles_advanced(self, asset: str, period: int, offset: int, time: int) -> List[Dict]:
|
|
485
527
|
"""
|
|
@@ -500,12 +542,209 @@ class PocketOptionAsync:
|
|
|
500
542
|
- close: Closing price
|
|
501
543
|
|
|
502
544
|
Note:
|
|
503
|
-
Available timeframes: 1, 5, 15, 30, 60, 300 seconds
|
|
504
|
-
Maximum period depends on the timeframe
|
|
545
|
+
- Available timeframes: 1, 5, 15, 30, 60, 300 seconds
|
|
546
|
+
- Maximum period depends on the timeframe
|
|
547
|
+
- WARNING: This function only fetches closed historical candles and is intended
|
|
548
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
549
|
+
for real-time/live trading as it does not include the current forming candle
|
|
550
|
+
and can introduce gaps if called sequentially during live trading.
|
|
551
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
505
552
|
"""
|
|
506
553
|
candles = await self.client.get_candles_advanced(asset, period, offset, time)
|
|
507
554
|
return json.loads(candles)
|
|
508
555
|
|
|
556
|
+
async def get_candles_live(
|
|
557
|
+
self,
|
|
558
|
+
asset: str,
|
|
559
|
+
period: int,
|
|
560
|
+
hours: float = 2.0,
|
|
561
|
+
max_rows: int = 100,
|
|
562
|
+
) -> AsyncGenerator[Tuple[List[Dict], Optional[Dict]], None]:
|
|
563
|
+
"""Fetches historical backfill and streams gap-free live candles.
|
|
564
|
+
|
|
565
|
+
This method subscribes to raw ticks first and buffers them, then fetches
|
|
566
|
+
historical candles (using get_candles_advanced, history, and compile_candles),
|
|
567
|
+
merges them, replays the buffered ticks, and yields updated candles (both
|
|
568
|
+
closed historical candles and the current forming candle) in real-time.
|
|
569
|
+
|
|
570
|
+
Args:
|
|
571
|
+
asset (str): Trading asset (e.g., "EURUSD_otc")
|
|
572
|
+
period (int): Candle timeframe in seconds (e.g., 60 for 1-minute candles)
|
|
573
|
+
hours (float): Hours of history to backfill. Defaults to 2.0.
|
|
574
|
+
max_rows (int): Maximum number of closed candles to retain in history. Defaults to 100.
|
|
575
|
+
|
|
576
|
+
Yields:
|
|
577
|
+
Tuple[List[Dict], Optional[Dict]]: A tuple containing:
|
|
578
|
+
- List[Dict]: List of closed candles (up to max_rows), each containing
|
|
579
|
+
'time', 'open', 'high', 'low', 'close'.
|
|
580
|
+
- Optional[Dict]: The currently forming candle, containing 'time', 'open',
|
|
581
|
+
'high', 'low', 'close', or None if not yet started.
|
|
582
|
+
"""
|
|
583
|
+
platform_time_offset = 7200
|
|
584
|
+
|
|
585
|
+
def bucket_start(timestamp: int, p: int) -> int:
|
|
586
|
+
return (timestamp // p) * p
|
|
587
|
+
|
|
588
|
+
def extract_time(candle: Dict) -> int:
|
|
589
|
+
val = int(float(candle.get("timestamp", candle.get("time", 0))))
|
|
590
|
+
if val > 10_000_000_000:
|
|
591
|
+
val //= 1000
|
|
592
|
+
return val - platform_time_offset
|
|
593
|
+
|
|
594
|
+
def merge_candles(*groups: List[Dict]) -> List[Dict]:
|
|
595
|
+
res: Dict[int, Dict] = {}
|
|
596
|
+
for group in groups:
|
|
597
|
+
for candle in group:
|
|
598
|
+
res[extract_time(candle)] = candle
|
|
599
|
+
return [res[ts] for ts in sorted(res)]
|
|
600
|
+
|
|
601
|
+
# Initialize feed
|
|
602
|
+
feed_candles: deque = deque(maxlen=max_rows)
|
|
603
|
+
forming: Optional[Dict] = None
|
|
604
|
+
|
|
605
|
+
def seed_history(history: List[Dict]) -> None:
|
|
606
|
+
cutoff = bucket_start(int(time.time()), period)
|
|
607
|
+
ordered = sorted(
|
|
608
|
+
(c for c in history if extract_time(c) < cutoff),
|
|
609
|
+
key=extract_time,
|
|
610
|
+
)
|
|
611
|
+
for c in ordered[-max_rows:]:
|
|
612
|
+
feed_candles.append(
|
|
613
|
+
{
|
|
614
|
+
"time": extract_time(c),
|
|
615
|
+
"open": float(c["open"]),
|
|
616
|
+
"high": float(c["high"]),
|
|
617
|
+
"low": float(c["low"]),
|
|
618
|
+
"close": float(c["close"]),
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
def ingest_tick(timestamp: int, price: float) -> None:
|
|
623
|
+
nonlocal forming
|
|
624
|
+
if forming is None:
|
|
625
|
+
start = bucket_start(timestamp, period)
|
|
626
|
+
forming = {
|
|
627
|
+
"time": start,
|
|
628
|
+
"open": price,
|
|
629
|
+
"high": price,
|
|
630
|
+
"low": price,
|
|
631
|
+
"close": price,
|
|
632
|
+
}
|
|
633
|
+
return
|
|
634
|
+
|
|
635
|
+
start = bucket_start(timestamp, period)
|
|
636
|
+
if start == forming["time"]:
|
|
637
|
+
forming["high"] = max(forming["high"], price)
|
|
638
|
+
forming["low"] = min(forming["low"], price)
|
|
639
|
+
forming["close"] = price
|
|
640
|
+
elif start > forming["time"]:
|
|
641
|
+
feed_candles.append(dict(forming))
|
|
642
|
+
forming = {
|
|
643
|
+
"time": start,
|
|
644
|
+
"open": price,
|
|
645
|
+
"high": price,
|
|
646
|
+
"low": price,
|
|
647
|
+
"close": price,
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
# 1. Subscribe to ticks FIRST
|
|
651
|
+
tick_buffer: List[Tuple[int, float]] = []
|
|
652
|
+
buffering = True
|
|
653
|
+
stream = await self.subscribe_symbol(asset)
|
|
654
|
+
|
|
655
|
+
queue = asyncio.Queue()
|
|
656
|
+
|
|
657
|
+
async def tick_reader():
|
|
658
|
+
nonlocal buffering
|
|
659
|
+
try:
|
|
660
|
+
async for tick in stream:
|
|
661
|
+
ts = extract_time(tick)
|
|
662
|
+
price = float(tick.get("close", tick.get("price", 0.0)))
|
|
663
|
+
if buffering:
|
|
664
|
+
tick_buffer.append((ts, price))
|
|
665
|
+
else:
|
|
666
|
+
ingest_tick(ts, price)
|
|
667
|
+
await queue.put((list(feed_candles), dict(forming) if forming else None))
|
|
668
|
+
except asyncio.CancelledError:
|
|
669
|
+
pass
|
|
670
|
+
finally:
|
|
671
|
+
await queue.put(None)
|
|
672
|
+
|
|
673
|
+
reader_task = asyncio.create_task(tick_reader())
|
|
674
|
+
|
|
675
|
+
try:
|
|
676
|
+
# 2. Fetch history while buffering ticks
|
|
677
|
+
offset_seconds = int(hours * 3600)
|
|
678
|
+
platform_time = int(time.time()) + platform_time_offset
|
|
679
|
+
|
|
680
|
+
try:
|
|
681
|
+
advanced_candles = await asyncio.wait_for(
|
|
682
|
+
self.get_candles_advanced(
|
|
683
|
+
asset,
|
|
684
|
+
period,
|
|
685
|
+
offset_seconds,
|
|
686
|
+
platform_time,
|
|
687
|
+
),
|
|
688
|
+
timeout=3.0
|
|
689
|
+
)
|
|
690
|
+
except Exception:
|
|
691
|
+
advanced_candles = []
|
|
692
|
+
|
|
693
|
+
try:
|
|
694
|
+
recent_candles = await asyncio.wait_for(
|
|
695
|
+
self.history(asset, period),
|
|
696
|
+
timeout=3.0
|
|
697
|
+
)
|
|
698
|
+
except Exception:
|
|
699
|
+
recent_candles = []
|
|
700
|
+
|
|
701
|
+
try:
|
|
702
|
+
compiled_candles = await asyncio.wait_for(
|
|
703
|
+
self.compile_candles(
|
|
704
|
+
asset,
|
|
705
|
+
period,
|
|
706
|
+
offset_seconds,
|
|
707
|
+
),
|
|
708
|
+
timeout=3.0
|
|
709
|
+
)
|
|
710
|
+
except Exception:
|
|
711
|
+
compiled_candles = []
|
|
712
|
+
|
|
713
|
+
history = merge_candles(
|
|
714
|
+
compiled_candles,
|
|
715
|
+
recent_candles,
|
|
716
|
+
advanced_candles,
|
|
717
|
+
)
|
|
718
|
+
seed_history(history)
|
|
719
|
+
|
|
720
|
+
# 3. Replay backlog
|
|
721
|
+
cutoff = 0
|
|
722
|
+
if feed_candles:
|
|
723
|
+
cutoff = feed_candles[-1]["time"] + period
|
|
724
|
+
for ts, price in sorted(tick_buffer):
|
|
725
|
+
if ts < cutoff:
|
|
726
|
+
continue
|
|
727
|
+
ingest_tick(ts, price)
|
|
728
|
+
|
|
729
|
+
buffering = False
|
|
730
|
+
# Yield initial seed state
|
|
731
|
+
yield list(feed_candles), dict(forming) if forming else None
|
|
732
|
+
|
|
733
|
+
# 4. Stream loop
|
|
734
|
+
while True:
|
|
735
|
+
item = await queue.get()
|
|
736
|
+
if item is None:
|
|
737
|
+
break
|
|
738
|
+
yield item
|
|
739
|
+
|
|
740
|
+
finally:
|
|
741
|
+
reader_task.cancel()
|
|
742
|
+
try:
|
|
743
|
+
await reader_task
|
|
744
|
+
except asyncio.CancelledError:
|
|
745
|
+
pass
|
|
746
|
+
await self.unsubscribe(asset)
|
|
747
|
+
|
|
509
748
|
async def balance(self) -> float:
|
|
510
749
|
"""
|
|
511
750
|
Retrieves current account balance.
|
|
@@ -987,6 +1226,14 @@ class PocketOptionAsync:
|
|
|
987
1226
|
|
|
988
1227
|
return json.loads(await self.client.compile_candles(asset, custom_period, lookback_period))
|
|
989
1228
|
|
|
1229
|
+
async def send_raw(self, message: str) -> None:
|
|
1230
|
+
"""Send a raw Engine.io/Socket.io message directly over the connection."""
|
|
1231
|
+
await self.client.send_raw(message)
|
|
1232
|
+
|
|
1233
|
+
async def subscribe_raw(self) -> AsyncRawSubscription:
|
|
1234
|
+
"""Subscribe to all incoming WebSocket messages verbatim."""
|
|
1235
|
+
return AsyncRawSubscription(await self.client.subscribe_raw())
|
|
1236
|
+
|
|
990
1237
|
async def subscribe_symbol(self, asset: str) -> AsyncSubscription:
|
|
991
1238
|
"""Subscribe to real-time raw price updates for an asset.
|
|
992
1239
|
|
|
@@ -1128,15 +1375,6 @@ class PocketOptionAsync:
|
|
|
1128
1375
|
"""Returns whether the SSID passed basic format validation during init."""
|
|
1129
1376
|
return self._ssid_valid
|
|
1130
1377
|
|
|
1131
|
-
def max_subscriptions(self) -> int:
|
|
1132
|
-
"""
|
|
1133
|
-
Returns the configured maximum number of concurrent subscriptions.
|
|
1134
|
-
|
|
1135
|
-
Returns:
|
|
1136
|
-
int: Maximum number of concurrent asset subscriptions allowed
|
|
1137
|
-
"""
|
|
1138
|
-
return self.client.max_subscriptions()
|
|
1139
|
-
|
|
1140
1378
|
async def disconnect(self) -> None:
|
|
1141
1379
|
"""
|
|
1142
1380
|
Disconnects the client while keeping the configuration intact.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import json
|
|
3
3
|
import threading
|
|
4
|
+
import sys
|
|
5
|
+
import warnings
|
|
4
6
|
from datetime import timedelta
|
|
5
7
|
from typing import Dict, List, Optional, Tuple, Union
|
|
6
|
-
import sys
|
|
7
|
-
|
|
8
8
|
from ..config import Config
|
|
9
9
|
from ..validator import Validator as Validator
|
|
10
10
|
from .asynchronous import PocketOptionAsync as PocketOptionAsync
|
|
@@ -25,6 +25,41 @@ class SyncSubscription:
|
|
|
25
25
|
return json.loads(next(self.subscription))
|
|
26
26
|
|
|
27
27
|
|
|
28
|
+
class SyncRawSubscription:
|
|
29
|
+
def __init__(self, subscription):
|
|
30
|
+
self.subscription = subscription
|
|
31
|
+
|
|
32
|
+
def __iter__(self):
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def __aiter__(self):
|
|
36
|
+
return self.subscription
|
|
37
|
+
|
|
38
|
+
def __next__(self):
|
|
39
|
+
return next(self.subscription)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class SyncCandleLiveIterator:
|
|
43
|
+
"""Synchronous iterator for live candle updates."""
|
|
44
|
+
|
|
45
|
+
def __init__(self, async_gen, loop):
|
|
46
|
+
self.async_gen = async_gen
|
|
47
|
+
self.loop = loop
|
|
48
|
+
|
|
49
|
+
def __iter__(self):
|
|
50
|
+
return self
|
|
51
|
+
|
|
52
|
+
def __next__(self):
|
|
53
|
+
async def get_next():
|
|
54
|
+
try:
|
|
55
|
+
return await self.async_gen.__anext__()
|
|
56
|
+
except StopAsyncIteration:
|
|
57
|
+
raise StopIteration
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
return asyncio.run_coroutine_threadsafe(get_next(), self.loop).result()
|
|
61
|
+
except StopIteration:
|
|
62
|
+
raise StopIteration
|
|
28
63
|
class RawHandlerSync:
|
|
29
64
|
"""Synchronous handler for advanced raw WebSocket message operations."""
|
|
30
65
|
|
|
@@ -126,11 +161,14 @@ class PocketOption:
|
|
|
126
161
|
_: Additional keyword arguments forwarded to the async client.
|
|
127
162
|
"""
|
|
128
163
|
self._lock = threading.RLock()
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
164
|
+
loop = asyncio.new_event_loop()
|
|
165
|
+
self._loop = loop
|
|
166
|
+
|
|
167
|
+
def _run_loop(loop_to_run):
|
|
168
|
+
asyncio.set_event_loop(loop_to_run)
|
|
169
|
+
loop_to_run.run_forever()
|
|
170
|
+
|
|
171
|
+
self._loop_thread = threading.Thread(target=_run_loop, args=(loop,), daemon=True)
|
|
134
172
|
self._loop_thread.start()
|
|
135
173
|
self._client = PocketOptionAsync(ssid, url=url, config=config)
|
|
136
174
|
future = asyncio.run_coroutine_threadsafe(self._client.wait_for_assets(), self._loop)
|
|
@@ -138,7 +176,7 @@ class PocketOption:
|
|
|
138
176
|
|
|
139
177
|
def __del__(self):
|
|
140
178
|
self._cleanup_loop()
|
|
141
|
-
|
|
179
|
+
|
|
142
180
|
def _cleanup_loop(self):
|
|
143
181
|
loop = getattr(self, "_loop", None)
|
|
144
182
|
if loop is None or loop.is_closed():
|
|
@@ -150,7 +188,7 @@ class PocketOption:
|
|
|
150
188
|
future.result(timeout=5)
|
|
151
189
|
except Exception:
|
|
152
190
|
pass
|
|
153
|
-
|
|
191
|
+
|
|
154
192
|
loop.call_soon_threadsafe(loop.stop)
|
|
155
193
|
thread = getattr(self, "_loop_thread", None)
|
|
156
194
|
if thread is not None and thread.is_alive():
|
|
@@ -158,7 +196,7 @@ class PocketOption:
|
|
|
158
196
|
# The daemon thread will be killed automatically, so just skip the join.
|
|
159
197
|
if not sys.is_finalizing():
|
|
160
198
|
thread.join(timeout=2)
|
|
161
|
-
|
|
199
|
+
|
|
162
200
|
try:
|
|
163
201
|
loop.close()
|
|
164
202
|
except Exception:
|
|
@@ -270,8 +308,24 @@ class PocketOption:
|
|
|
270
308
|
|
|
271
309
|
Returns:
|
|
272
310
|
A list of candle dictionaries.
|
|
273
|
-
|
|
274
|
-
|
|
311
|
+
|
|
312
|
+
Note:
|
|
313
|
+
WARNING: This function only fetches closed historical candles and is intended
|
|
314
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
315
|
+
for real-time/live trading as it does not include the current forming candle
|
|
316
|
+
and can introduce gaps if called sequentially during live trading.
|
|
317
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
318
|
+
"""
|
|
319
|
+
warnings.warn(
|
|
320
|
+
"get_candles() is deprecated and will be removed in a new release. "
|
|
321
|
+
"Please use get_candles_live() for live gap-free candles instead.",
|
|
322
|
+
DeprecationWarning,
|
|
323
|
+
stacklevel=2,
|
|
324
|
+
)
|
|
325
|
+
hours = max(0.1, offset / 3600.0)
|
|
326
|
+
iterator = self.get_candles_live(asset, period, hours=hours)
|
|
327
|
+
closed, forming = next(iterator)
|
|
328
|
+
return closed
|
|
275
329
|
|
|
276
330
|
def get_candles_advanced(self, asset: str, period: int, offset: int, time: int) -> List[Dict]:
|
|
277
331
|
"""Get historical candle data with a specific reference time.
|
|
@@ -284,6 +338,13 @@ class PocketOption:
|
|
|
284
338
|
|
|
285
339
|
Returns:
|
|
286
340
|
A list of candle dictionaries.
|
|
341
|
+
|
|
342
|
+
Note:
|
|
343
|
+
WARNING: This function only fetches closed historical candles and is intended
|
|
344
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
345
|
+
for real-time/live trading as it does not include the current forming candle
|
|
346
|
+
and can introduce gaps if called sequentially during live trading.
|
|
347
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
287
348
|
"""
|
|
288
349
|
return self._run(self._client.get_candles_advanced(asset, period, offset, time))
|
|
289
350
|
|
|
@@ -296,8 +357,57 @@ class PocketOption:
|
|
|
296
357
|
|
|
297
358
|
Returns:
|
|
298
359
|
A list of candle dictionaries.
|
|
360
|
+
|
|
361
|
+
Note:
|
|
362
|
+
WARNING: This function only fetches closed historical candles and is intended
|
|
363
|
+
for training models, backtesting, or historical analysis. It is NOT designed
|
|
364
|
+
for real-time/live trading as it does not include the current forming candle
|
|
365
|
+
and can introduce gaps if called sequentially during live trading.
|
|
366
|
+
For live gap-free candle feeds, use `get_candles_live()` instead.
|
|
367
|
+
"""
|
|
368
|
+
warnings.warn(
|
|
369
|
+
"candles() is deprecated and will be removed in a new release. "
|
|
370
|
+
"Please use get_candles_live() for live gap-free candles instead.",
|
|
371
|
+
DeprecationWarning,
|
|
372
|
+
stacklevel=2,
|
|
373
|
+
)
|
|
374
|
+
iterator = self.get_candles_live(asset, period, hours=2.0)
|
|
375
|
+
closed, forming = next(iterator)
|
|
376
|
+
return closed
|
|
377
|
+
|
|
378
|
+
def get_candles_live(
|
|
379
|
+
self,
|
|
380
|
+
asset: str,
|
|
381
|
+
period: int,
|
|
382
|
+
hours: float = 2.0,
|
|
383
|
+
max_rows: int = 100,
|
|
384
|
+
) -> SyncCandleLiveIterator:
|
|
385
|
+
"""Fetches historical backfill and streams live candles.
|
|
386
|
+
|
|
387
|
+
This method subscribes to raw ticks first and buffers them, then fetches
|
|
388
|
+
historical candles, merges them, replays the buffered ticks, and returns
|
|
389
|
+
a generator yielding updated candles (both closed historical candles and
|
|
390
|
+
the current forming candle) in real-time.
|
|
391
|
+
|
|
392
|
+
Args:
|
|
393
|
+
asset: Trading asset (e.g., "EURUSD_otc")
|
|
394
|
+
period: Candle timeframe in seconds (e.g., 60 for 1-minute candles)
|
|
395
|
+
hours: Hours of history to backfill. Defaults to 2.0.
|
|
396
|
+
max_rows: Maximum number of closed candles to retain in history. Defaults to 100.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
An iterator yielding (closed_candles, forming_candle).
|
|
299
400
|
"""
|
|
300
|
-
|
|
401
|
+
async def create_gen():
|
|
402
|
+
return self._client.get_candles_live(
|
|
403
|
+
asset=asset,
|
|
404
|
+
period=period,
|
|
405
|
+
hours=hours,
|
|
406
|
+
max_rows=max_rows,
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
async_gen = self._run(create_gen())
|
|
410
|
+
return SyncCandleLiveIterator(async_gen, self.loop)
|
|
301
411
|
|
|
302
412
|
def balance(self) -> float:
|
|
303
413
|
"""Get the current account balance.
|
|
@@ -442,6 +552,14 @@ class PocketOption:
|
|
|
442
552
|
"""
|
|
443
553
|
return self._run(self._client.compile_candles(asset, custom_period, lookback_period))
|
|
444
554
|
|
|
555
|
+
def send_raw(self, message: str) -> None:
|
|
556
|
+
"""Send a raw Engine.io/Socket.io message directly over the connection."""
|
|
557
|
+
self._run(self._client.send_raw(message))
|
|
558
|
+
|
|
559
|
+
def subscribe_raw(self) -> SyncRawSubscription:
|
|
560
|
+
"""Subscribe to all incoming WebSocket messages verbatim."""
|
|
561
|
+
return SyncRawSubscription(self._run(self._client.subscribe_raw()))
|
|
562
|
+
|
|
445
563
|
def subscribe_symbol(self, asset: str) -> SyncSubscription:
|
|
446
564
|
"""Subscribe to real-time price updates for a symbol.
|
|
447
565
|
|
|
@@ -537,14 +655,6 @@ class PocketOption:
|
|
|
537
655
|
"""
|
|
538
656
|
return self._client.is_connected()
|
|
539
657
|
|
|
540
|
-
def max_subscriptions(self) -> int:
|
|
541
|
-
"""Get the maximum number of concurrent subscriptions.
|
|
542
|
-
|
|
543
|
-
Returns:
|
|
544
|
-
The maximum number of allowed subscriptions.
|
|
545
|
-
"""
|
|
546
|
-
return self._client.max_subscriptions()
|
|
547
|
-
|
|
548
658
|
def wait_for_assets(self, timeout: float = 60.0) -> None:
|
|
549
659
|
"""Wait for asset data to finish loading.
|
|
550
660
|
|