|
| 1 | +"""Module for Pocket Option API.""" |
| 2 | +import asyncio |
| 3 | +import datetime |
| 4 | +import time |
| 5 | +import json |
| 6 | +import logging |
| 7 | +import threading |
| 8 | +import requests |
| 9 | +import ssl |
| 10 | +import atexit |
| 11 | +from collections import deque |
| 12 | +from pocketoptionapi.ws.client import WebsocketClient |
| 13 | +from pocketoptionapi.ws.chanels.get_balances import * |
| 14 | + |
| 15 | +from pocketoptionapi.ws.chanels.ssid import Ssid |
| 16 | +# from pocketoptionapi.ws.chanels.subscribe import * |
| 17 | +# from pocketoptionapi.ws.chanels.unsubscribe import * |
| 18 | +# from pocketoptionapi.ws.chanels.setactives import SetActives |
| 19 | +from pocketoptionapi.ws.chanels.candles import GetCandles |
| 20 | +# from pocketoptionapi.ws.chanels.buyv2 import Buyv2 |
| 21 | +from pocketoptionapi.ws.chanels.buyv3 import * |
| 22 | +# from pocketoptionapi.ws.chanels.user import * |
| 23 | +# from pocketoptionapi.ws.chanels.api_game_betinfo import Game_betinfo |
| 24 | +# from pocketoptionapi.ws.chanels.instruments import Get_instruments |
| 25 | +# from pocketoptionapi.ws.chanels.get_financial_information import GetFinancialInformation |
| 26 | +# from pocketoptionapi.ws.chanels.strike_list import Strike_list |
| 27 | +# from pocketoptionapi.ws.chanels.leaderboard import Leader_Board |
| 28 | + |
| 29 | +# from pocketoptionapi.ws.chanels.traders_mood import Traders_mood_subscribe |
| 30 | +# from pocketoptionapi.ws.chanels.traders_mood import Traders_mood_unsubscribe |
| 31 | +# from pocketoptionapi.ws.chanels.buy_place_order_temp import Buy_place_order_temp |
| 32 | +# from pocketoptionapi.ws.chanels.get_order import Get_order |
| 33 | +# from pocketoptionapi.ws.chanels.get_deferred_orders import GetDeferredOrders |
| 34 | +# from pocketoptionapi.ws.chanels.get_positions import * |
| 35 | + |
| 36 | +# from pocketoptionapi.ws.chanels.get_available_leverages import Get_available_leverages |
| 37 | +# from pocketoptionapi.ws.chanels.cancel_order import Cancel_order |
| 38 | +# from pocketoptionapi.ws.chanels.close_position import Close_position |
| 39 | +# from pocketoptionapi.ws.chanels.get_overnight_fee import Get_overnight_fee |
| 40 | +# from pocketoptionapi.ws.chanels.heartbeat import Heartbeat |
| 41 | + |
| 42 | +# from pocketoptionapi.ws.chanels.digital_option import * |
| 43 | +# from pocketoptionapi.ws.chanels.api_game_getoptions import * |
| 44 | +# from pocketoptionapi.ws.chanels.sell_option import Sell_Option |
| 45 | +# from pocketoptionapi.ws.chanels.change_tpsl import Change_Tpsl |
| 46 | +# from pocketoptionapi.ws.chanels.change_auto_margin_call import ChangeAutoMarginCall |
| 47 | + |
| 48 | +from pocketoptionapi.ws.objects.timesync import TimeSync |
| 49 | +# from pocketoptionapi.ws.objects.profile import Profile |
| 50 | +from pocketoptionapi.ws.objects.candles import Candles |
| 51 | +# from pocketoptionapi.ws.objects.listinfodata import ListInfoData |
| 52 | +# from pocketoptionapi.ws.objects.betinfo import Game_betinfo_data |
| 53 | +import pocketoptionapi.global_value as global_value |
| 54 | +from collections import defaultdict |
| 55 | + |
| 56 | + |
| 57 | +def nested_dict(n, type): |
| 58 | + if n == 1: |
| 59 | + return defaultdict(type) |
| 60 | + else: |
| 61 | + return defaultdict(lambda: nested_dict(n - 1, type)) |
| 62 | + |
| 63 | + |
| 64 | +# InsecureRequestWarning: Unverified HTTPS request is being made. |
| 65 | +# Adding certificate verification is strongly advised. |
| 66 | +# See: https://urllib3.readthedocs.org/en/latest/security.html |
| 67 | + |
| 68 | + |
| 69 | +class PocketOptionAPI(object): # pylint: disable=too-many-instance-attributes |
| 70 | + """Class for communication with Pocket Option API.""" |
| 71 | + |
| 72 | + # pylint: disable=too-many-public-methods |
| 73 | + socket_option_opened = {} |
| 74 | + timesync = TimeSync() |
| 75 | + # profile = Profile() |
| 76 | + candles = Candles() |
| 77 | + # listinfodata = ListInfoData() |
| 78 | + api_option_init_all_result = [] |
| 79 | + api_option_init_all_result_v2 = [] |
| 80 | + # for digital |
| 81 | + underlying_list_data = None |
| 82 | + position_changed = None |
| 83 | + instrument_quites_generated_data = nested_dict(2, dict) |
| 84 | + instrument_quotes_generated_raw_data = nested_dict(2, dict) |
| 85 | + instrument_quites_generated_timestamp = nested_dict(2, dict) |
| 86 | + strike_list = None |
| 87 | + leaderboard_deals_client = None |
| 88 | + # position_changed_data = nested_dict(2, dict) |
| 89 | + # microserviceName_binary_options_name_option=nested_dict(2,dict) |
| 90 | + order_async = None |
| 91 | + # game_betinfo = Game_betinfo_data() |
| 92 | + instruments = None |
| 93 | + financial_information = None |
| 94 | + buy_id = None |
| 95 | + buy_order_id = None |
| 96 | + traders_mood = {} # get hight(put) % |
| 97 | + order_data = None |
| 98 | + positions = None |
| 99 | + position = None |
| 100 | + deferred_orders = None |
| 101 | + position_history = None |
| 102 | + position_history_v2 = None |
| 103 | + available_leverages = None |
| 104 | + order_canceled = None |
| 105 | + close_position_data = None |
| 106 | + overnight_fee = None |
| 107 | + # ---for real time |
| 108 | + digital_option_placed_id = None |
| 109 | + live_deal_data = nested_dict(3, deque) |
| 110 | + |
| 111 | + subscribe_commission_changed_data = nested_dict(2, dict) |
| 112 | + real_time_candles = nested_dict(3, dict) |
| 113 | + real_time_candles_maxdict_table = nested_dict(2, dict) |
| 114 | + candle_generated_check = nested_dict(2, dict) |
| 115 | + candle_generated_all_size_check = nested_dict(1, dict) |
| 116 | + # ---for api_game_getoptions_result |
| 117 | + api_game_getoptions_result = None |
| 118 | + sold_options_respond = None |
| 119 | + tpsl_changed_respond = None |
| 120 | + auto_margin_call_changed_respond = None |
| 121 | + top_assets_updated_data = {} |
| 122 | + get_options_v2_data = None |
| 123 | + # --for binary option multi buy |
| 124 | + buy_multi_result = None |
| 125 | + buy_multi_option = {} |
| 126 | + # |
| 127 | + result = None |
| 128 | + training_balance_reset_request = None |
| 129 | + balances_raw = None |
| 130 | + user_profile_client = None |
| 131 | + leaderboard_userinfo_deals_client = None |
| 132 | + users_availability = None |
| 133 | + history_data = None |
| 134 | + historyNew = None |
| 135 | + |
| 136 | + # ------------------ |
| 137 | + |
| 138 | + def __init__(self, proxies=None): |
| 139 | + """ |
| 140 | + :param dict proxies: (optional) The http request proxies. |
| 141 | + """ |
| 142 | + self.websocket_client = None |
| 143 | + self.websocket_thread = None |
| 144 | + # self.wss_url = "wss://api-us-north.po.market/socket.io/?EIO=4&transport=websocket" |
| 145 | + self.session = requests.Session() |
| 146 | + self.session.verify = False |
| 147 | + self.session.trust_env = False |
| 148 | + self.proxies = proxies |
| 149 | + # is used to determine if a buyOrder was set or failed. If |
| 150 | + # it is None, there had been no buy order yet or just send. |
| 151 | + # If it is false, the last failed |
| 152 | + # If it is true, the last buy order was successful |
| 153 | + self.buy_successful = None |
| 154 | + self.loop = asyncio.get_event_loop() |
| 155 | + self.websocket_client = WebsocketClient(self) |
| 156 | + |
| 157 | + @property |
| 158 | + def websocket(self): |
| 159 | + """Property to get websocket. |
| 160 | +
|
| 161 | + :returns: The instance of :class:`WebSocket <websocket.WebSocket>`. |
| 162 | + """ |
| 163 | + return self.websocket_client |
| 164 | + |
| 165 | + def send_websocket_request(self, name, msg, request_id="", no_force_send=True): |
| 166 | + """Send websocket request to IQ Option server. |
| 167 | +
|
| 168 | + :param no_force_send: |
| 169 | + :param request_id: |
| 170 | + :param str name: The websocket request name. |
| 171 | + :param dict msg: The websocket request msg. |
| 172 | + """ |
| 173 | + |
| 174 | + logger = logging.getLogger(__name__) |
| 175 | + |
| 176 | + # data = json.dumps(dict(name=name, msg=msg, request_id=request_id)) |
| 177 | + data = f'42{json.dumps(msg)}' |
| 178 | + |
| 179 | + while (global_value.ssl_Mutual_exclusion or global_value.ssl_Mutual_exclusion_write) and no_force_send: |
| 180 | + |
| 181 | + pass |
| 182 | + global_value.ssl_Mutual_exclusion_write = True |
| 183 | + |
| 184 | + # self.websocket_client.send_message(data) |
| 185 | + loop = asyncio.new_event_loop() |
| 186 | + asyncio.set_event_loop(loop) |
| 187 | + |
| 188 | + # Ejecutar la corutina connect dentro del bucle de eventos del nuevo hilo |
| 189 | + loop.run_until_complete(self.websocket.send_message(data)) |
| 190 | + |
| 191 | + logger.debug(data) |
| 192 | + global_value.ssl_Mutual_exclusion_write = False |
| 193 | + |
| 194 | + def start_websocket(self): |
| 195 | + global_value.websocket_is_connected = False |
| 196 | + global_value.check_websocket_if_error = False |
| 197 | + global_value.websocket_error_reason = None |
| 198 | + |
| 199 | + # Obtener o crear un nuevo bucle de eventos para este hilo |
| 200 | + loop = asyncio.new_event_loop() |
| 201 | + asyncio.set_event_loop(loop) |
| 202 | + |
| 203 | + # Ejecutar la corutina connect dentro del bucle de eventos del nuevo hilo |
| 204 | + loop.run_until_complete(self.websocket.connect()) |
| 205 | + loop.run_forever() |
| 206 | + |
| 207 | + while True: |
| 208 | + try: |
| 209 | + if global_value.check_websocket_if_error: |
| 210 | + return False, global_value.websocket_error_reason |
| 211 | + if global_value.websocket_is_connected is False: |
| 212 | + return False, "Websocket connection closed." |
| 213 | + elif global_value.websocket_is_connected is True: |
| 214 | + return True, None |
| 215 | + |
| 216 | + except: |
| 217 | + pass |
| 218 | + pass |
| 219 | + |
| 220 | + def connect(self): |
| 221 | + """Method for connection to Pocket Option API.""" |
| 222 | + |
| 223 | + global_value.ssl_Mutual_exclusion = False |
| 224 | + global_value.ssl_Mutual_exclusion_write = False |
| 225 | + |
| 226 | + try: |
| 227 | + self.close() |
| 228 | + except: |
| 229 | + pass |
| 230 | + |
| 231 | + check_websocket, websocket_reason = self.start_websocket() |
| 232 | + |
| 233 | + if not check_websocket: |
| 234 | + return check_websocket, websocket_reason |
| 235 | + |
| 236 | + self.timesync.server_timestamps = None |
| 237 | + while True: |
| 238 | + try: |
| 239 | + if self.timesync.server_timestamps is not None: |
| 240 | + break |
| 241 | + except: |
| 242 | + pass |
| 243 | + return True, None |
| 244 | + |
| 245 | + def close(self): |
| 246 | + self.websocket.close() |
| 247 | + self.websocket_thread.join() |
| 248 | + |
| 249 | + def websocket_alive(self): |
| 250 | + return self.websocket_thread.is_alive() |
| 251 | + |
| 252 | + @property |
| 253 | + def get_balances(self): |
| 254 | + """Property for get IQ Option http getprofile resource. |
| 255 | +
|
| 256 | + :returns: The instance of :class:`Login |
| 257 | + <iqoptionapi.http.getprofile.Getprofile>`. |
| 258 | + """ |
| 259 | + return Get_Balances(self) |
| 260 | + |
| 261 | + # ____________for_______binary_______option_____________ |
| 262 | + |
| 263 | + @property |
| 264 | + def buyv3(self): |
| 265 | + return Buyv3(self) |
| 266 | + |
| 267 | + @property |
| 268 | + def getcandles(self): |
| 269 | + """Property for get IQ Option websocket candles chanel. |
| 270 | +
|
| 271 | + :returns: The instance of :class:`GetCandles |
| 272 | + <iqoptionapi.ws.chanels.candles.GetCandles>`. |
| 273 | + """ |
| 274 | + return GetCandles(self) |
0 commit comments