BinaryOptionsToolsV2 0.2.12__cp39-abi3-win32.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.
- BinaryOptionsToolsV2/BinaryOptionsToolsV2.pyd +0 -0
- BinaryOptionsToolsV2/BinaryOptionsToolsV2.pyi +172 -0
- BinaryOptionsToolsV2/__init__.py +60 -0
- BinaryOptionsToolsV2/config.py +124 -0
- BinaryOptionsToolsV2/pocketoption/__init__.py +21 -0
- BinaryOptionsToolsV2/pocketoption/asynchronous.py +1523 -0
- BinaryOptionsToolsV2/pocketoption/synchronous.py +659 -0
- BinaryOptionsToolsV2/pocketoption/tools/__init__.py +7 -0
- BinaryOptionsToolsV2/pocketoption/tools/login.py +515 -0
- BinaryOptionsToolsV2/tracing.py +91 -0
- BinaryOptionsToolsV2/validator.py +76 -0
- binaryoptionstoolsv2-0.2.12.dist-info/METADATA +535 -0
- binaryoptionstoolsv2-0.2.12.dist-info/RECORD +16 -0
- binaryoptionstoolsv2-0.2.12.dist-info/WHEEL +4 -0
- binaryoptionstoolsv2-0.2.12.dist-info/licenses/LICENSE +100 -0
- binaryoptionstoolsv2-0.2.12.dist-info/sboms/BinaryOptionsToolsV2.cyclonedx.json +7910 -0
|
Binary file
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
from typing import Any, Callable, List, Optional, Tuple
|
|
2
|
+
|
|
3
|
+
class Action:
|
|
4
|
+
Call: "Action"
|
|
5
|
+
Put: "Action"
|
|
6
|
+
|
|
7
|
+
class PyConfig:
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
max_allowed_loops: int = 10,
|
|
11
|
+
sleep_interval: int = 100,
|
|
12
|
+
reconnect_time: int = 5,
|
|
13
|
+
connection_initialization_timeout: float = 30.0,
|
|
14
|
+
timeout: float = 10.0,
|
|
15
|
+
urls: List[str] = [],
|
|
16
|
+
) -> None: ...
|
|
17
|
+
|
|
18
|
+
class RawValidator:
|
|
19
|
+
@staticmethod
|
|
20
|
+
def new() -> "RawValidator": ...
|
|
21
|
+
@staticmethod
|
|
22
|
+
def regex(pattern: str) -> "RawValidator": ...
|
|
23
|
+
@staticmethod
|
|
24
|
+
def contains(pattern: str) -> "RawValidator": ...
|
|
25
|
+
@staticmethod
|
|
26
|
+
def starts_with(pattern: str) -> "RawValidator": ...
|
|
27
|
+
@staticmethod
|
|
28
|
+
def ends_with(pattern: str) -> "RawValidator": ...
|
|
29
|
+
@staticmethod
|
|
30
|
+
def ne(validator: "RawValidator") -> "RawValidator": ...
|
|
31
|
+
@staticmethod
|
|
32
|
+
def all(validators: List["RawValidator"]) -> "RawValidator": ...
|
|
33
|
+
@staticmethod
|
|
34
|
+
def any(validators: List["RawValidator"]) -> "RawValidator": ...
|
|
35
|
+
@staticmethod
|
|
36
|
+
def custom(func: Callable[[str], bool]) -> "RawValidator": ...
|
|
37
|
+
def check(self, msg: str) -> bool: ...
|
|
38
|
+
|
|
39
|
+
class StreamIterator:
|
|
40
|
+
def __aiter__(self) -> "StreamIterator": ...
|
|
41
|
+
def __anext__(self) -> str: ...
|
|
42
|
+
def __iter__(self) -> "StreamIterator": ...
|
|
43
|
+
def __next__(self) -> str: ...
|
|
44
|
+
|
|
45
|
+
class RawStreamIterator:
|
|
46
|
+
def __aiter__(self) -> "RawStreamIterator": ...
|
|
47
|
+
def __anext__(self) -> str: ...
|
|
48
|
+
def __iter__(self) -> "RawStreamIterator": ...
|
|
49
|
+
def __next__(self) -> str: ...
|
|
50
|
+
|
|
51
|
+
class RawHandler:
|
|
52
|
+
def id(self) -> str: ...
|
|
53
|
+
async def send_text(self, text: str) -> None: ...
|
|
54
|
+
async def send_binary(self, data: bytes) -> None: ...
|
|
55
|
+
async def send_and_wait(self, message: str) -> str: ...
|
|
56
|
+
async def wait_next(self) -> str: ...
|
|
57
|
+
async def subscribe(self) -> RawStreamIterator: ...
|
|
58
|
+
|
|
59
|
+
class RawHandle:
|
|
60
|
+
async def create(self, validator: RawValidator, keep_alive_message: Optional[str]) -> RawHandler: ...
|
|
61
|
+
async def remove(self, id: str) -> bool: ...
|
|
62
|
+
|
|
63
|
+
class RawPocketOption:
|
|
64
|
+
def __init__(self, ssid: str) -> None: ...
|
|
65
|
+
@staticmethod
|
|
66
|
+
async def create(ssid: str) -> "RawPocketOption": ...
|
|
67
|
+
@staticmethod
|
|
68
|
+
def new_with_url(ssid: str, url: str) -> "RawPocketOption": ...
|
|
69
|
+
@staticmethod
|
|
70
|
+
async def create_with_url(ssid: str, url: str) -> "RawPocketOption": ...
|
|
71
|
+
@staticmethod
|
|
72
|
+
def new_with_config(ssid: str, config: PyConfig) -> "RawPocketOption": ...
|
|
73
|
+
@staticmethod
|
|
74
|
+
async def create_with_config(ssid: str, config: PyConfig) -> "RawPocketOption": ...
|
|
75
|
+
async def wait_for_assets(self, timeout_secs: float) -> None: ...
|
|
76
|
+
def is_demo(self) -> bool: ...
|
|
77
|
+
async def buy(self, asset: str, amount: float, time: int) -> List[str]: ...
|
|
78
|
+
async def sell(self, asset: str, amount: float, time: int) -> List[str]: ...
|
|
79
|
+
async def check_win(self, trade_id: str) -> str: ...
|
|
80
|
+
async def get_deal_end_time(self, trade_id: str) -> Optional[int]: ...
|
|
81
|
+
async def candles(self, asset: str, period: int) -> str: ...
|
|
82
|
+
async def get_candles(self, asset: str, period: int, offset: int) -> str: ...
|
|
83
|
+
async def get_candles_advanced(self, asset: str, period: int, offset: int, time: int) -> str: ...
|
|
84
|
+
async def balance(self) -> float: ...
|
|
85
|
+
async def open_pending_order(
|
|
86
|
+
self,
|
|
87
|
+
open_type: int,
|
|
88
|
+
amount: float,
|
|
89
|
+
asset: str,
|
|
90
|
+
open_time: int,
|
|
91
|
+
open_price: float,
|
|
92
|
+
timeframe: int,
|
|
93
|
+
min_payout: int,
|
|
94
|
+
command: int,
|
|
95
|
+
) -> str: ...
|
|
96
|
+
async def closed_deals(self) -> str: ...
|
|
97
|
+
async def get_closed_deal(self, id: str) -> Optional[str]: ...
|
|
98
|
+
async def clear_closed_deals(self) -> None: ...
|
|
99
|
+
async def opened_deals(self) -> str: ...
|
|
100
|
+
async def get_opened_deal(self, id: str) -> Optional[str]: ...
|
|
101
|
+
async def payout(self) -> str: ...
|
|
102
|
+
async def history(self, asset: str, period: int) -> str: ...
|
|
103
|
+
async def compile_candles(self, asset: str, custom_period: int, lookback_period: int) -> str: ...
|
|
104
|
+
async def subscribe_symbol(self, symbol: str) -> StreamIterator: ...
|
|
105
|
+
async def subscribe_symbol_chunked(self, symbol: str, chunk_size: int) -> StreamIterator: ...
|
|
106
|
+
async def subscribe_symbol_timed(self, symbol: str, time: Any) -> StreamIterator: ...
|
|
107
|
+
async def subscribe_symbol_time_aligned(self, symbol: str, time: Any) -> StreamIterator: ...
|
|
108
|
+
async def send_raw_message(self, message: str) -> None: ...
|
|
109
|
+
async def create_raw_order(self, message: str, validator: RawValidator) -> str: ...
|
|
110
|
+
async def create_raw_order_with_timeout(self, message: str, validator: RawValidator, timeout: Any) -> str: ...
|
|
111
|
+
async def create_raw_order_with_timeout_and_retry(
|
|
112
|
+
self, message: str, validator: RawValidator, timeout: Any
|
|
113
|
+
) -> str: ...
|
|
114
|
+
async def create_raw_iterator(
|
|
115
|
+
self, message: str, validator: RawValidator, timeout: Optional[Any]
|
|
116
|
+
) -> RawStreamIterator: ...
|
|
117
|
+
async def get_server_time(self) -> int: ...
|
|
118
|
+
async def disconnect(self) -> None: ...
|
|
119
|
+
async def connect(self) -> None: ...
|
|
120
|
+
async def reconnect(self) -> None: ...
|
|
121
|
+
async def unsubscribe(self, asset: str) -> None: ...
|
|
122
|
+
async def create_raw_handler(self, validator: RawValidator, keep_alive: Optional[str]) -> RawHandler: ...
|
|
123
|
+
|
|
124
|
+
class Logger:
|
|
125
|
+
def __init__(self) -> None: ...
|
|
126
|
+
def debug(self, message: str) -> None: ...
|
|
127
|
+
def info(self, message: str) -> None: ...
|
|
128
|
+
def warn(self, message: str) -> None: ...
|
|
129
|
+
def error(self, message: str) -> None: ...
|
|
130
|
+
|
|
131
|
+
class LogBuilder:
|
|
132
|
+
def __init__(self) -> None: ...
|
|
133
|
+
def create_logs_iterator(self, level: str, timeout: Optional[Any]) -> Any: ...
|
|
134
|
+
def log_file(self, path: str, level: str) -> None: ...
|
|
135
|
+
def terminal(self, level: str) -> None: ...
|
|
136
|
+
def build(self) -> None: ...
|
|
137
|
+
|
|
138
|
+
class StreamLogsLayer: ...
|
|
139
|
+
class StreamLogsIterator: ...
|
|
140
|
+
|
|
141
|
+
class PyContext:
|
|
142
|
+
async def buy(self, asset: str, amount: float, time: int) -> List[str]: ...
|
|
143
|
+
async def balance(self) -> float: ...
|
|
144
|
+
|
|
145
|
+
class PyVirtualMarket:
|
|
146
|
+
def __init__(self, initial_balance: float) -> None: ...
|
|
147
|
+
async def update_price(self, asset: str, price: float) -> None: ...
|
|
148
|
+
|
|
149
|
+
class PyStrategy:
|
|
150
|
+
current_candle: int
|
|
151
|
+
def __init__(self) -> None: ...
|
|
152
|
+
def on_start(self, ctx: PyContext) -> None: ...
|
|
153
|
+
def on_candle(self, ctx: PyContext, asset: str, candle_json: str) -> None: ...
|
|
154
|
+
def on_balance(self, ctx: PyContext, balance: float) -> None: ...
|
|
155
|
+
def trade(self, ctx: PyContext, asset: str, amount: float, timeframe: int, direction: Action) -> List[str]: ...
|
|
156
|
+
def result(self, ctx: PyContext, id: str) -> str: ...
|
|
157
|
+
def add(self, name: str, indicator: Any) -> None: ...
|
|
158
|
+
def get(self, name: str) -> Optional[Any]: ...
|
|
159
|
+
def list_indicators(self) -> List[Tuple[str, str]]: ...
|
|
160
|
+
def update(self, candle: str) -> None: ...
|
|
161
|
+
def reset(self) -> None: ...
|
|
162
|
+
def period(self) -> int: ...
|
|
163
|
+
|
|
164
|
+
class PyBot:
|
|
165
|
+
def __init__(
|
|
166
|
+
self, client: RawPocketOption, strategy: PyStrategy, virtual_market: Optional[PyVirtualMarket] = None
|
|
167
|
+
) -> None: ...
|
|
168
|
+
def with_update_interval(self, millis: int) -> None: ...
|
|
169
|
+
def add_asset(self, asset: str, period: int) -> None: ...
|
|
170
|
+
async def run(self) -> None: ...
|
|
171
|
+
|
|
172
|
+
def start_tracing(path: str, level: str, terminal: bool, layers: List[StreamLogsLayer]) -> None: ...
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from .config import Config as Config
|
|
5
|
+
from . import tracing as tracing
|
|
6
|
+
from . import validator as validator
|
|
7
|
+
from .pocketoption import (
|
|
8
|
+
PocketOptionAsync as PocketOptionAsync,
|
|
9
|
+
PocketOption as PocketOption,
|
|
10
|
+
RawHandler as RawHandler,
|
|
11
|
+
Validator as Validator,
|
|
12
|
+
__all__ as __pocket_all__,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Import the Rust module and re-export its attributes
|
|
16
|
+
_rust_module = None
|
|
17
|
+
try:
|
|
18
|
+
_rust_module = importlib.import_module(".BinaryOptionsToolsV2", __package__)
|
|
19
|
+
except (ImportError, ValueError):
|
|
20
|
+
try:
|
|
21
|
+
_rust_module = importlib.import_module("BinaryOptionsToolsV2")
|
|
22
|
+
if _rust_module is sys.modules.get(__package__):
|
|
23
|
+
_rust_module = None
|
|
24
|
+
except ImportError:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
if _rust_module is not None:
|
|
28
|
+
globals().update({k: v for k, v in _rust_module.__dict__.items() if not k.startswith("_")})
|
|
29
|
+
elif os.environ.get("PYTEST_CURRENT_TEST"):
|
|
30
|
+
print(f"[ERROR] Rust extension module not found (__package__={__package__})")
|
|
31
|
+
|
|
32
|
+
# Names expected from the Rust cdylib; only those actually loaded will be available
|
|
33
|
+
_rust_exported_names = [
|
|
34
|
+
"RawPocketOption",
|
|
35
|
+
"RawValidator",
|
|
36
|
+
"RawHandler",
|
|
37
|
+
"RawHandle",
|
|
38
|
+
"Logger",
|
|
39
|
+
"LogBuilder",
|
|
40
|
+
"PyConfig",
|
|
41
|
+
"PyBot",
|
|
42
|
+
"PyStrategy",
|
|
43
|
+
"PyContext",
|
|
44
|
+
"PyVirtualMarket",
|
|
45
|
+
"Action",
|
|
46
|
+
"StreamLogsIterator",
|
|
47
|
+
"StreamLogsLayer",
|
|
48
|
+
"StreamIterator",
|
|
49
|
+
"RawStreamIterator",
|
|
50
|
+
"start_tracing",
|
|
51
|
+
]
|
|
52
|
+
__rust_all__ = [n for n in _rust_exported_names if n in globals()]
|
|
53
|
+
|
|
54
|
+
__all__ = list(
|
|
55
|
+
set(
|
|
56
|
+
__pocket_all__
|
|
57
|
+
+ ["tracing", "validator", "PocketOptionAsync", "PocketOption", "RawHandler", "Validator"]
|
|
58
|
+
+ __rust_all__
|
|
59
|
+
)
|
|
60
|
+
)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import sys
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Dict, List
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _get_pyconfig():
|
|
8
|
+
"""Get the PyConfig class from the compiled Rust module via package namespace."""
|
|
9
|
+
pkg = sys.modules.get(__package__ or "")
|
|
10
|
+
if pkg is not None and hasattr(pkg, "PyConfig"):
|
|
11
|
+
return pkg.PyConfig
|
|
12
|
+
import BinaryOptionsToolsV2 as _mod
|
|
13
|
+
|
|
14
|
+
return _mod.PyConfig
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class Config:
|
|
19
|
+
"""
|
|
20
|
+
Python wrapper around PyConfig that provides additional functionality
|
|
21
|
+
for configuration management.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
max_allowed_loops: int = 100
|
|
25
|
+
sleep_interval: int = 100
|
|
26
|
+
reconnect_time: int = 5
|
|
27
|
+
connection_initialization_timeout_secs: int = 60
|
|
28
|
+
timeout_secs: int = 30
|
|
29
|
+
urls: List[str] = field(default_factory=list)
|
|
30
|
+
max_subscriptions: int = 4
|
|
31
|
+
|
|
32
|
+
# Logging configuration
|
|
33
|
+
terminal_logging: bool = False
|
|
34
|
+
log_level: str = "INFO"
|
|
35
|
+
|
|
36
|
+
# Extra duration, used by functions like `check_win`
|
|
37
|
+
extra_duration: int = 5
|
|
38
|
+
|
|
39
|
+
def __post_init__(self):
|
|
40
|
+
self.urls = self.urls or []
|
|
41
|
+
self._pyconfig = None
|
|
42
|
+
self._locked = False
|
|
43
|
+
|
|
44
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
45
|
+
if name.startswith("_") or not hasattr(self, "_locked") or not self._locked:
|
|
46
|
+
super().__setattr__(name, value)
|
|
47
|
+
else:
|
|
48
|
+
raise RuntimeError("Configuration is locked and cannot be modified after being used")
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def pyconfig(self) -> Any:
|
|
52
|
+
"""Returns the PyConfig instance for use in Rust code, then locks config."""
|
|
53
|
+
if self._pyconfig is None:
|
|
54
|
+
self._pyconfig = _get_pyconfig()()
|
|
55
|
+
self._sync_pyconfig()
|
|
56
|
+
self._locked = True
|
|
57
|
+
return self._pyconfig
|
|
58
|
+
|
|
59
|
+
def _sync_pyconfig(self):
|
|
60
|
+
"""Sync all Python config fields to the Rust PyConfig instance."""
|
|
61
|
+
if self._pyconfig is None:
|
|
62
|
+
self._pyconfig = _get_pyconfig()()
|
|
63
|
+
|
|
64
|
+
self._pyconfig.max_allowed_loops = self.max_allowed_loops
|
|
65
|
+
self._pyconfig.sleep_interval = self.sleep_interval
|
|
66
|
+
self._pyconfig.reconnect_time = self.reconnect_time
|
|
67
|
+
self._pyconfig.connection_initialization_timeout_secs = self.connection_initialization_timeout_secs
|
|
68
|
+
self._pyconfig.timeout_secs = self.timeout_secs
|
|
69
|
+
self._pyconfig.urls = self.urls
|
|
70
|
+
self._pyconfig.max_subscriptions = self.max_subscriptions
|
|
71
|
+
|
|
72
|
+
def _validate(self):
|
|
73
|
+
"""Validate config values, raising ValueError on invalid input."""
|
|
74
|
+
if self.max_allowed_loops < 0:
|
|
75
|
+
raise ValueError("max_allowed_loops must be non-negative")
|
|
76
|
+
if self.sleep_interval < 0:
|
|
77
|
+
raise ValueError("sleep_interval must be non-negative")
|
|
78
|
+
if self.reconnect_time < 1:
|
|
79
|
+
raise ValueError("reconnect_time must be at least 1 second")
|
|
80
|
+
if self.connection_initialization_timeout_secs < 1:
|
|
81
|
+
raise ValueError("connection_initialization_timeout_secs must be at least 1")
|
|
82
|
+
if self.timeout_secs < 1:
|
|
83
|
+
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
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def from_dict(cls, config_dict: Dict[str, Any]) -> "Config":
|
|
89
|
+
"""Creates a Config instance from a dictionary."""
|
|
90
|
+
cfg = cls(**{k: v for k, v in config_dict.items() if k in cls.__dataclass_fields__})
|
|
91
|
+
cfg._validate()
|
|
92
|
+
return cfg
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def from_json(cls, json_str: str) -> "Config":
|
|
96
|
+
"""Creates a Config instance from a JSON string."""
|
|
97
|
+
return cls.from_dict(json.loads(json_str))
|
|
98
|
+
|
|
99
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
100
|
+
"""Converts the configuration to a dictionary."""
|
|
101
|
+
return {
|
|
102
|
+
"max_allowed_loops": self.max_allowed_loops,
|
|
103
|
+
"sleep_interval": self.sleep_interval,
|
|
104
|
+
"reconnect_time": self.reconnect_time,
|
|
105
|
+
"connection_initialization_timeout_secs": self.connection_initialization_timeout_secs,
|
|
106
|
+
"timeout_secs": self.timeout_secs,
|
|
107
|
+
"urls": self.urls,
|
|
108
|
+
"max_subscriptions": self.max_subscriptions,
|
|
109
|
+
"terminal_logging": self.terminal_logging,
|
|
110
|
+
"log_level": self.log_level,
|
|
111
|
+
"extra_duration": self.extra_duration,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
def to_json(self) -> str:
|
|
115
|
+
"""Converts the configuration to a JSON string."""
|
|
116
|
+
return json.dumps(self.to_dict())
|
|
117
|
+
|
|
118
|
+
def update(self, config_dict: Dict[str, Any]) -> None:
|
|
119
|
+
"""Updates config from a dictionary. Raises RuntimeError if locked."""
|
|
120
|
+
if self._locked:
|
|
121
|
+
raise RuntimeError("Configuration is locked and cannot be modified after being used")
|
|
122
|
+
for key, value in config_dict.items():
|
|
123
|
+
if hasattr(self, key):
|
|
124
|
+
setattr(self, key, value)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module for Pocket Option related functionality.
|
|
3
|
+
|
|
4
|
+
Contains asynchronous and synchronous clients,
|
|
5
|
+
as well as specific classes for Pocket Option trading.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"asynchronous",
|
|
10
|
+
"login",
|
|
11
|
+
"login_async",
|
|
12
|
+
"PocketOptionAsync",
|
|
13
|
+
"PocketOption",
|
|
14
|
+
"RawHandler",
|
|
15
|
+
"RawHandlerSync",
|
|
16
|
+
"Validator",
|
|
17
|
+
]
|
|
18
|
+
from .tools.login import login, login_async
|
|
19
|
+
from . import asynchronous, synchronous as synchronous
|
|
20
|
+
from .asynchronous import PocketOptionAsync, RawHandler, Validator
|
|
21
|
+
from .synchronous import PocketOption, RawHandlerSync
|