├── requirements.txt ├── setup.py ├── ornek_soket.py ├── config.py ├── README.md ├── ornek.py ├── algolab_socket.py └── algolab.py /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.23.3 2 | pandas==1.5.0 3 | pycryptodome==3.16.0 4 | requests==2.28.1 5 | setuptools==65.6.3 6 | websocket_client==1.4.2 7 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='AlgoLab', 5 | version='1.11', 6 | description='Algolab Python code for BIST trading', 7 | author='Atilla Yurtseven', 8 | author_email='quant@atilla.io', 9 | url='https://github.com/atillayurtseven/AlgoLab', 10 | packages=['AlgoLab'], 11 | install_requires=['certifi==2022.9.24', 'charset-normalizer==2.1.1', 'idna==3.4', 'numpy==1.23.3', 'pandas==1.5.0', 'pycryptodome==3.16.0', 'python-dateutil==2.8.2', 'pytz==2022.4', 'requests==2.28.1', 'six==1.16.0', 'urllib3==1.26.12', 'websocket-client==1.4.1'], 12 | ) -------------------------------------------------------------------------------- /ornek_soket.py: -------------------------------------------------------------------------------- 1 | from algolab import AlgoLab 2 | from algolab_socket import AlgoLabSocket 3 | import json 4 | import time 5 | 6 | # USER INFO 7 | API_KEY = "API_KEY" 8 | USERNAME = "TC_KİMLİK_NO" 9 | PASSWORD = "DENİZBANK_ŞİFRENİZ" 10 | 11 | if __name__ == "__main__": 12 | 13 | algo = AlgoLab(api_key=API_KEY, username=USERNAME, password=PASSWORD, auto_login=True) 14 | soket = AlgoLabSocket(algo.api_key, algo.hash, "T") 15 | soket.connect() 16 | while not soket.connected: 17 | time.sleep(0.05) 18 | 19 | data = {"Type": "T", "Symbols": ["GARAN", "TSKB"]} 20 | soket.send(data) 21 | 22 | i = 0 23 | while soket.connected: 24 | data = soket.recv() 25 | i += 1 26 | if data: 27 | try: 28 | msg = json.loads(data) 29 | print(msg) 30 | except: 31 | print("error 1") 32 | soket.close() 33 | break -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | version = "3.0.1" 2 | hostname = "www.algolab.com.tr" 3 | api_hostname = f"https://{hostname}" 4 | api_url = api_hostname + "/api" 5 | socket_url = f"wss://{hostname}/api/ws" 6 | 7 | # MARKETS 8 | MARKETS = { 9 | "VIP": "BIST30 VIOP", 10 | "KIYM": "KIYMETLİ MADENLER", 11 | "FX": "FOREX", 12 | "IMKBH": "BIST SPOT", 13 | "IMKBX": "ENDEKS", 14 | "INTUSD": "", 15 | "INTEUR": "", 16 | } 17 | 18 | # ENDPOINTS 19 | URL_LOGIN_USER = "/api/LoginUser" 20 | URL_LOGIN_CONTROL = "/api/LoginUserControl" 21 | URL_GETEQUITYINFO = "/api/GetEquityInfo" 22 | URL_GETSUBACCOUNTS = "/api/GetSubAccounts" 23 | URL_INSTANTPOSITION = "/api/InstantPosition" 24 | URL_TODAYTRANSACTION = "/api/TodaysTransaction" 25 | URL_VIOPCUSTOMEROVERALL = "/api/ViopCustomerOverall" 26 | URL_VIOPCUSTOMERTRANSACTIONS = "/api/ViopCustomerTransactions" 27 | URL_SENDORDER = "/api/SendOrder" 28 | URL_MODIFYORDER = "/api/ModifyOrder" 29 | URL_DELETEORDER = "/api/DeleteOrder" 30 | URL_DELETEORDERVIOP = "/api/DeleteOrderViop" 31 | URL_SESSIONREFRESH = "/api/SessionRefresh" 32 | URL_GETCANDLEDATA = "/api/GetCandleData" 33 | URL_VIOPCOLLETERALINFO = "/api/ViopCollateralInfo" 34 | URL_RISKSIMULATION = "/api/RiskSimulation" 35 | URL_GETEQUITYORDERHISTORY = "/api/GetEquityOrderHistory" 36 | URL_GETVIOPORDERHISTORY = "/api/GetViopOrderHistory" 37 | URL_CASHFLOW = "/api/CashFlow" 38 | URL_ACCOUNTEXTRE = "/api/AccountExtre" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # AlgoLab Python Wrapper 3 | 4 | ## Genel Bakış 5 | Bu proje, AlgoLab API'si için bir Python wrapper'ıdır. `algolab.py` ve `algolab_socket.py` modülleri aracılığıyla AlgoLab API'sine erişim sağlar. Kullanıcıların AlgoLab platformundaki verilere programatik olarak erişmelerini ve işlemler yapmalarını kolaylaştırır. 6 | 7 | ## Kurulum 8 | Projeyi kullanmak için, bu repoyu klonlayın ve gerekli bağımlılıkları kurun. 9 | 10 | ``` 11 | git clone [repo-url] 12 | cd [repo-directory] 13 | pip install -r requirements.txt 14 | ``` 15 | 16 | ## Kullanım 17 | API'yi kullanmak için, öncelikle `config.py` dosyasında gerekli yapılandırmaları yapın. Daha sonra `algolab.py` ve `algolab_socket.py` modüllerini projenizde import ederek kullanabilirsiniz. 18 | 19 | Örnek kullanım: 20 | 21 | ```python 22 | from algolab import AlgoLab 23 | from algolab_socket import AlgoLabSocket 24 | 25 | # API ile etkileşim 26 | algolab = AlgoLab(api_key="your_api_key", username="your_username", password="your_password") 27 | response = algolab.your_method() 28 | 29 | # Soket ile etkileşim 30 | socket = AlgoLabSocket(api_key="your_api_key", hash="your_hash") 31 | socket.connect() 32 | ``` 33 | 34 | ## Yapılandırma 35 | `config.py` dosyası, API ve soket bağlantıları için temel yapılandırmaları içerir. API'nin hostname'i ve diğer sabitler bu dosyada tanımlanır. 36 | 37 | ## Bağımlılıklar 38 | Bu wrapper'ın çalışması için gerekli bağımlılıklar `requirements.txt` dosyasında listelenmelidir. 39 | 40 | ## AlgoLab Link 41 | https://algolab.com.tr/ 42 | 43 | ## Lisans ve Yazar Bilgisi 44 | Bu proje MIT altında yayınlanmıştır. 45 | Atilla Yurtseven 46 | --- 47 | 48 | Bu dokümantasyon, projenin temel kullanımını ve yapılandırmasını anlatmaktadır. Daha detaylı bilgi ve örnekler için, lütfen kod içindeki yorumları inceleyin. 49 | -------------------------------------------------------------------------------- /ornek.py: -------------------------------------------------------------------------------- 1 | from algolab import AlgoLab 2 | import pandas as pd 3 | import numpy as np 4 | import datetime 5 | 6 | # USER INFO 7 | API_KEY = "API_KEY" 8 | USERNAME = "TC_KİMLİK_NO" 9 | PASSWORD = "DENİZBANK_ŞİFRENİZ" 10 | 11 | if __name__ == "__main__": 12 | symbol = "GARAN" 13 | period = "60" # 60 dk 14 | d = AlgoLab(api_key=API_KEY, username=USERNAME, password=PASSWORD) 15 | # Login olarak, token alıyoruz 16 | if d.LoginUser(): 17 | # token ile hash algoritmasını alıyoruz 18 | if d.LoginUserControl(): 19 | # GARAN hissesinin 60 dk'lık geçmişini alıyoruz. DİKKAT: Seans içindeyseniz son bar henüz kapanmamıştır. 20 | candle = d.GetCandleData(symbol, period) 21 | if candle: 22 | print(candle) 23 | try: 24 | succ = candle["success"] 25 | if succ: 26 | ohlc = [] 27 | content = candle["content"] 28 | for i in range(len(content)): 29 | d = content[i]["date"] 30 | try: 31 | dt = datetime.datetime.strptime(d, "%Y-%m-%dT%H:%M:%S").strftime("%Y-%m-%d %H:%M:%S") 32 | except: 33 | dt = datetime.datetime.strptime(d, "%Y-%m-%dT%H:%M:%S%z").strftime("%Y-%m-%d %H:%M:%S") 34 | o = content[i]["open"] 35 | h = content[i]["high"] 36 | l = content[i]["low"] 37 | c = content[i]["close"] 38 | ohlc.append([dt, o, h, l, c]) 39 | # oluşturduğumuz listi pandas dataframe'e aktarıyoruz 40 | df = pd.DataFrame(columns=["date", "open", "high", "low", "close"], data=np.array(ohlc)) 41 | print(df.tail()) 42 | except Exception as e: 43 | print(f"Hata oluştu: {e}") 44 | else: 45 | print("Login kontrolü başarısız oldu") 46 | else: 47 | print("Login başarısız oldu") 48 | 49 | print("Sonlandırıldı") 50 | -------------------------------------------------------------------------------- /algolab_socket.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import hashlib, json, datetime, ssl, socket 3 | from websocket import create_connection, WebSocketTimeoutException, WebSocketConnectionClosedException 4 | from config import * 5 | 6 | class AlgoLabSocket(): 7 | def __init__(self, api_key, hash, verbose=True, callback=None, timeout=0, ping_timer=900): 8 | """ 9 | :String api_key: API_KEY 10 | :String hash: LoginUserControl'den dönen Hash kodu 11 | :Obj callback: Soketin veriyi göndereceği fonksiyon 12 | """ 13 | self.ping_timer = ping_timer 14 | self.last_ping = datetime.datetime.now() 15 | self.timeout = timeout 16 | self.verbose = verbose 17 | self.callback = callback 18 | self._connected = False 19 | self.ws = None 20 | self.api_key = api_key 21 | self.hash = hash 22 | self.data = self.api_key + api_hostname + "/ws" 23 | self.checker = hashlib.sha256(self.data.encode('utf-8')).hexdigest() 24 | self.request_time = datetime.datetime.now() 25 | self.headers = { 26 | "APIKEY": self.api_key, 27 | "Authorization": self.hash, 28 | "Checker": self.checker 29 | } 30 | 31 | def close(self): 32 | self._connected = False 33 | self.ws = None 34 | 35 | def connect(self): 36 | if self.verbose: 37 | print("Socket bağlantısı kuruluyor...") 38 | context = ssl.create_default_context() 39 | context.set_ciphers("DEFAULT") 40 | try: 41 | if self.timeout > 0: 42 | sock = socket.create_connection((hostname, 443), timeout=self.timeout) 43 | else: 44 | sock = socket.create_connection((hostname, 443)) 45 | ssock = context.wrap_socket(sock, server_hostname=hostname) 46 | self.ws = create_connection(socket_url, socket=ssock, header=self.headers) 47 | self._connected = True 48 | self.last_ping = datetime.datetime.now() 49 | except Exception as e: 50 | self.close() 51 | print(f"Socket Hatası: {e}") 52 | if self.verbose: 53 | print("Socket bağlantısı başarılı.") 54 | #self.verbose = False 55 | 56 | def recv(self): 57 | try: 58 | data = self.ws.recv() 59 | except WebSocketTimeoutException: 60 | data = "" 61 | except WebSocketConnectionClosedException: 62 | print("Connection closed") 63 | self.close() 64 | return False 65 | except Exception as e: 66 | print("Recv Error:", e) 67 | self.close() 68 | return False 69 | if self.heart_beat: 70 | r = self.ping() 71 | return data 72 | 73 | def send(self, d): 74 | """ 75 | :param d: Dict 76 | """ 77 | try: 78 | data = {"token": self.hash} 79 | for s in d: 80 | data[s] = d[s] 81 | resp = self.ws.send(json.dumps(data)) 82 | except Exception as e: 83 | print("Send Error:", e) 84 | resp = None 85 | self.close() 86 | return resp 87 | 88 | def ping(self): 89 | data = {"Type": "H"} 90 | return self.send(data) 91 | 92 | def get_heart_beat(self): 93 | t = datetime.datetime.now() 94 | r = (t - self.last_ping).seconds > self.ping_timer 95 | if r: 96 | self.last_ping = datetime.datetime.now() 97 | return r 98 | 99 | def get_connected(self): 100 | return self._connected 101 | 102 | connected = property(get_connected) 103 | heart_beat = property(get_heart_beat) 104 | -------------------------------------------------------------------------------- /algolab.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import requests, hashlib, json, base64, inspect, time 3 | from Crypto.Cipher import AES 4 | from Crypto.Util.Padding import pad 5 | from threading import Thread 6 | from config import * 7 | 8 | last_request = 0.0 9 | LOCK = False 10 | 11 | class AlgoLab(): 12 | def __init__(self, api_key, username, password, auto_login=True, keep_alive=True, freq=1.1, verbose=True): 13 | """ 14 | api_key: API_KEY 15 | username: TC Kimlik No 16 | password: DENIZBANK_HESAP_ŞİFRENİZ 17 | verbose: True, False - İşlemlerin çıktısını yazdırır 18 | freq: float: İşlemler arası en az beklenmesi gereken süre 19 | """ 20 | if verbose: 21 | print("Sistem hazırlanıyor...") 22 | try: 23 | self.api_code = api_key.split("-")[1] 24 | except: 25 | self.api_code = api_key 26 | self.api_key = "API-" + self.api_code 27 | self.username = username 28 | self.password = password 29 | self.api_hostname = api_hostname 30 | self.api_url = api_url 31 | self.auto_login = auto_login 32 | self.freq = freq 33 | self.headers = {"APIKEY": self.api_key} 34 | self.keep_alive = keep_alive 35 | self.thread_keepalive = Thread(target=self.ping) 36 | self.verbose = verbose 37 | self.token = "" 38 | self.new_hour = False 39 | self.sms_code = "" 40 | self.hash = "" 41 | self.start() 42 | 43 | def save_settings(self): 44 | try: 45 | data = { 46 | "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 47 | "token": self.token, 48 | "hash": self.hash 49 | } 50 | with open("./data.json", "w") as f: 51 | # Dosyaya yaz 52 | json.dump(data, f) 53 | return True 54 | except Exception as e: 55 | print(f"Seçenekler kaydedilirken hata oluştu: {e}") 56 | return False 57 | 58 | def load_settings(self): 59 | try: 60 | with open("./data.json", "r") as f: 61 | data = json.load(f) 62 | self.token = data["token"] 63 | self.hash = data["hash"] 64 | return True 65 | except Exception as e: 66 | print(f"Seçenekler yüklenirken hata oluştu: {e}") 67 | return False 68 | 69 | def start(self): 70 | if self.auto_login: 71 | # önceki login bilgileri varsa yükle 72 | s = self.load_settings() 73 | if not s or not self.is_alive: 74 | if self.verbose: 75 | print("Login zaman aşımına uğradı. Yeniden giriş yapılıyor...") 76 | if self.LoginUser(): 77 | self.LoginUserControl() 78 | else: 79 | if self.verbose: 80 | print("Otomatik login başarılı...") 81 | if self.keep_alive: 82 | self.thread_keepalive.start() 83 | 84 | def ping(self): 85 | while self.keep_alive: 86 | p = self.SessionRefresh(silent=True) 87 | time.sleep(60 * 15) 88 | 89 | # LOGIN 90 | 91 | def LoginUser(self): 92 | try: 93 | if self.verbose: 94 | print("Login işlemi yapılıyor...") 95 | f = inspect.stack()[0][3] 96 | u = self.encrypt(self.username) 97 | p = self.encrypt(self.password) 98 | payload = {"username": u, "password": p} 99 | endpoint = URL_LOGIN_USER 100 | resp = self.post(endpoint=endpoint, payload=payload, login=True) 101 | login_user = self.error_check(resp, f) 102 | if not login_user: 103 | return False 104 | login_user = resp.json() 105 | succ = login_user["success"] 106 | msg = login_user["message"] 107 | content = login_user["content"] 108 | if succ: 109 | self.token = content["token"] 110 | if self.verbose: 111 | print("Login başarılı.") 112 | return True 113 | else: 114 | if self.verbose: 115 | print(f"Login Başarısız. Mesaj: {msg}") 116 | except Exception as e: 117 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 118 | 119 | def LoginUserControl(self): 120 | try: 121 | if self.verbose: 122 | print("Login kontrolü yapılıyor...") 123 | self.sms_code = input("Cep telefonunuza gelen SMS kodunu girin: ") 124 | f = inspect.stack()[0][3] 125 | t = self.encrypt(self.token) 126 | s = self.encrypt(self.sms_code) 127 | payload = {'token': t, 'password': s} 128 | endpoint = URL_LOGIN_CONTROL 129 | resp = self.post(endpoint, payload=payload, login=True) 130 | login_control = self.error_check(resp, f) 131 | if not login_control: 132 | return False 133 | login_control = resp.json() 134 | succ = login_control["success"] 135 | msg = login_control["message"] 136 | content = login_control["content"] 137 | if succ: 138 | self.hash = content["hash"] 139 | if self.verbose: 140 | print("Login kontrolü başarılı.") 141 | self.save_settings() 142 | return True 143 | else: 144 | if self.verbose: 145 | print(f"Login kontrolü başarısız.\nMesaj: {msg}") 146 | except Exception as e: 147 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 148 | 149 | # REQUESTS 150 | 151 | def SessionRefresh(self, silent=False): 152 | try: 153 | f = inspect.stack()[0][3] 154 | endpoint = URL_SESSIONREFRESH 155 | payload = {} 156 | resp = self.post(endpoint, payload=payload) 157 | return self.error_check(resp, f, silent) 158 | except Exception as e: 159 | if not silent: 160 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 161 | 162 | def Portfolio(self): 163 | try: 164 | f = inspect.stack()[0][3] 165 | endpoint = URL_PORTOLIO 166 | payload = {"Subaccount": ""} 167 | resp = self.post(endpoint, payload=payload) 168 | return self.error_check(resp, f) 169 | except Exception as e: 170 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 171 | 172 | def GetEquityInfo(self, symbol): 173 | """ 174 | :String symbol: Sembol Kodu Örn: ARCLK 175 | """ 176 | try: 177 | f = inspect.stack()[0][3] 178 | endpoint = URL_GETEQUITYINFO 179 | payload = {'symbol': symbol} 180 | resp = self.post(endpoint, payload=payload) 181 | return self.error_check(resp, f) 182 | except Exception as e: 183 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 184 | 185 | def GetSubAccounts(self, silent=False): 186 | try: 187 | f = inspect.stack()[0][3] 188 | end_point = URL_GETSUBACCOUNTS 189 | resp = self.post(end_point, {}) 190 | return self.error_check(resp, f, silent=silent) 191 | except Exception as e: 192 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 193 | 194 | def GetInstantPosition(self, sub_account=""): 195 | try: 196 | f = inspect.stack()[0][3] 197 | end_point = URL_INSTANTPOSITION 198 | payload = {'Subaccount': sub_account} 199 | resp = self.post(end_point, payload) 200 | return self.error_check(resp, f) 201 | except Exception as e: 202 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 203 | 204 | def GetTodaysTransaction(self, sub_account=""): 205 | try: 206 | f = inspect.stack()[0][3] 207 | end_point = URL_TODAYTRANSACTION 208 | payload = {'Subaccount': sub_account} 209 | resp = self.post(end_point, payload) 210 | return self.error_check(resp, f) 211 | except Exception as e: 212 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 213 | 214 | def GetViopCustomerOverall(self, sub_account=""): 215 | try: 216 | f = inspect.stack()[0][3] 217 | end_point = URL_VIOPCUSTOMEROVERALL 218 | payload = {'Subaccount': sub_account} 219 | resp = self.post(end_point, payload) 220 | return self.error_check(resp, f) 221 | except Exception as e: 222 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 223 | 224 | def GetViopCustomerTransactions(self, sub_account=""): 225 | try: 226 | f = inspect.stack()[0][3] 227 | end_point = URL_VIOPCUSTOMERTRANSACTIONS 228 | payload = {'Subaccount': sub_account} 229 | resp = self.post(end_point, payload) 230 | return self.error_check(resp, f) 231 | except Exception as e: 232 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 233 | 234 | def GetCandleData(self, symbol, period): 235 | try: 236 | f = inspect.stack()[0][3] 237 | end_point = URL_GETCANDLEDATA 238 | payload = { 239 | 'symbol': symbol, 240 | 'period': period 241 | } 242 | resp = self.post(end_point, payload) 243 | return self.error_check(resp, f) 244 | except Exception as e: 245 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 246 | 247 | def RiskSimulation(self, sub_account=""): 248 | try: 249 | f = inspect.stack()[0][3] 250 | end_point = URL_RISKSIMULATION 251 | payload = {'Subaccount': sub_account} 252 | resp = self.post(end_point, payload) 253 | return self.error_check(resp, f) 254 | except Exception as e: 255 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 256 | 257 | def CashFlow(self, sub_account=""): 258 | try: 259 | f = inspect.stack()[0][3] 260 | end_point = URL_CASHFLOW 261 | payload = {'Subaccount': sub_account} 262 | resp = self.post(end_point, payload) 263 | return self.error_check(resp, f) 264 | except Exception as e: 265 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 266 | 267 | # ORDERS 268 | 269 | def SendOrder(self, symbol, direction, pricetype, lot, price=0.0, sms=False, email=False, subAccount=""): 270 | """ 271 | :String symbol: Sembol Kodu 272 | :String direction: İşlem Yönü: BUY / SELL (Alış/Satış) 273 | :String pricetype: Emir Tipi: piyasa/limit 274 | :String price: Emir tipi limit ise fiyat girilmelidir. (Örn. 1.98 şeklinde girilmelidir.) 275 | :String lot: Emir Adeti 276 | :Bool sms: Sms Gönderim 277 | :Bool email: Email Gönderim 278 | :String subAccount: Alt Hesap Numarası “Boş gönderilebilir. Boş gönderilir ise Aktif Hesap Bilgilerini getirir.” 279 | 280 | Örnek Body: 281 | { 282 | "symbol": "TSKB", 283 | "direction": "BUY", 284 | "pricetype": "limit", 285 | "price": "2.01", 286 | "lot": "1", 287 | "sms": True, 288 | "email": False, 289 | "Subaccount": "" 290 | } 291 | """ 292 | try: 293 | end_point = URL_SENDORDER 294 | payload = { 295 | "symbol": symbol, 296 | "direction": direction, 297 | "pricetype": pricetype, 298 | "price": str(price), 299 | "lot": str(lot), 300 | "sms": sms, 301 | "email": email, 302 | "subAccount": subAccount 303 | } 304 | #if not price is None: 305 | # payload["price"] = str(price) 306 | resp = self.post(end_point, payload) 307 | try: 308 | data = resp.json() 309 | return data 310 | except: 311 | f = inspect.stack()[0][3] 312 | print(f"{f}() fonksiyonunda veri tipi hatası. Veri, json formatından farklı geldi:") 313 | print(resp.text) 314 | except Exception as e: 315 | f = inspect.stack()[0][3] 316 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 317 | 318 | def ModifyOrder(self, id, price, lot, viop, subAccount): 319 | """ 320 | :String id: Emrin ID’ si 321 | :String price: Düzeltilecek Fiyat 322 | :String lot: Lot Miktarı (Viop emri ise girilmelidir.) 323 | :Bool viop: Emrin Viop emri olduğunu belirtir. “Viop emri ise true olmalıdır.” 324 | :String subAccount: Alt Hesap Numarası “Boş gönderilebilir. Boş gönderilir ise Aktif Hesap Bilgilerini getirir.” 325 | 326 | Örnek Body 327 | { 328 | "id":"001VEV", 329 | "price":"2.04", 330 | "lot":"0", 331 | "viop":false, 332 | "Subaccount":"" 333 | } 334 | """ 335 | try: 336 | end_point = URL_MODIFYORDER 337 | payload = { 338 | 'id': id, 339 | 'price': price, 340 | 'lot': lot, 341 | 'viop': viop, 342 | 'subAccount': subAccount 343 | } 344 | resp = self.post(end_point, payload) 345 | try: 346 | data = resp.json() 347 | return data 348 | except: 349 | f = inspect.stack()[0][3] 350 | print(f"{f}() fonksiyonunda veri tipi hatası. Veri, json formatından farklı geldi:") 351 | print(resp.text) 352 | except Exception as e: 353 | f = inspect.stack()[0][3] 354 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 355 | 356 | def DeleteOrder(self, id, subAccount): 357 | """ 358 | :String id: Emrin ID’ si 359 | :String subAccount: Alt Hesap Numarası “Boş gönderilebilir. Boş gönderilir ise Aktif Hesap Bilgilerini getirir.” 360 | 361 | Örnek Body 362 | { 363 | "id":"001VEV", 364 | "subAccount":"" 365 | } 366 | """ 367 | try: 368 | end_point = URL_DELETEORDER 369 | payload = { 370 | 'id': id, 371 | 'subAccount': subAccount 372 | } 373 | resp = self.post(end_point, payload) 374 | try: 375 | data = resp.json() 376 | return data 377 | except: 378 | f = inspect.stack()[0][3] 379 | print(f"{f}() fonksiyonunda veri tipi hatası. Veri, json formatından farklı geldi:") 380 | print(resp.text) 381 | except Exception as e: 382 | f = inspect.stack()[0][3] 383 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 384 | 385 | def DeleteOrderViop(self, id, adet, subAccount): 386 | """ 387 | :String id: Emrin ID’ si 388 | :String adet: İptal edilecek adet 389 | :String subAccount: Alt Hesap Numarası “Boş gönderilebilir. Boş gönderilir ise Aktif Hesap Bilgilerini getirir.” 390 | 391 | Örnek Body 392 | { 393 | "id":"001VEV", 394 | "adet":"1", 395 | "subAccount":"" 396 | } 397 | """ 398 | try: 399 | end_point = URL_DELETEORDER 400 | payload = { 401 | 'id': id, 402 | 'adet': adet, 403 | 'subAccount': subAccount 404 | } 405 | resp = self.post(end_point, payload) 406 | try: 407 | data = resp.json() 408 | return data 409 | except: 410 | f = inspect.stack()[0][3] 411 | print(f"{f}() fonksiyonunda veri tipi hatası. Veri, json formatından farklı geldi:") 412 | print(resp.text) 413 | except Exception as e: 414 | f = inspect.stack()[0][3] 415 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 416 | 417 | # TOOLS 418 | def AccountExtre(self, sub_account="", start_date=None, end_date=None): 419 | """ 420 | start_date: başlangıç tarihi "2023-07-01 00:00:00" formatında 421 | end_date: bitiş tarihi "2023-07-01 00:00:00" formatında 422 | """ 423 | try: 424 | f = inspect.stack()[0][3] 425 | end_point = URL_ACCOUNTEXTRE 426 | payload = {'Subaccount': sub_account, 427 | 'start': start_date, 428 | 'end': end_date 429 | } 430 | resp = self.post(end_point, payload) 431 | return self.error_check(resp, f) 432 | except Exception as e: 433 | print(f"{f}() fonsiyonunda hata oluştu: {e}") 434 | 435 | def get_is_alive(self): 436 | try: 437 | #resp = self.SessionRefresh(silent=True) 438 | resp = self.GetSubAccounts(silent=True) 439 | return resp["success"] 440 | except: 441 | return False 442 | 443 | def get_logged_in(self): 444 | return self.is_alive 445 | 446 | def error_check(self, resp, f, silent=False): 447 | try: 448 | if resp.status_code == 200: 449 | data = resp.json() 450 | return data 451 | else: 452 | if not silent: 453 | print(f"Error kodu: {resp.status_code}") 454 | print(resp.text) 455 | return False 456 | except: 457 | if not silent: 458 | print(f"{f}() fonksiyonunda veri tipi hatası. Veri, json formatından farklı geldi:") 459 | print(resp.text) 460 | return False 461 | 462 | def encrypt(self, text): 463 | iv = b'\0' * 16 464 | key = base64.b64decode(self.api_code.encode('utf-8')) 465 | cipher = AES.new(key, AES.MODE_CBC, iv) 466 | bytes = text.encode() 467 | padded_bytes = pad(bytes, 16) 468 | r = cipher.encrypt(padded_bytes) 469 | return base64.b64encode(r).decode("utf-8") 470 | 471 | def make_checker(self, endpoint, payload): 472 | if len(payload) > 0: 473 | body = json.dumps(payload).replace(' ', '') 474 | else: 475 | body = "" 476 | data = self.api_key + self.api_hostname + endpoint + body 477 | checker = hashlib.sha256(data.encode('utf-8')).hexdigest() 478 | return checker 479 | 480 | def _request(self, method, url, endpoint, payload, headers): 481 | global last_request, LOCK 482 | while LOCK: 483 | time.sleep(0.1) 484 | LOCK = True 485 | try: 486 | tries = 0 487 | while True: 488 | tries += 1 489 | try: 490 | response = "" 491 | if method == "POST": 492 | t = time.time() 493 | diff = t - last_request 494 | wait_for = last_request > 0.0 and diff < self.freq # son işlemden geçen süre freq saniyeden küçükse bekle 495 | if wait_for: 496 | time.sleep(self.freq - diff + 0.1) 497 | response = requests.post(url + endpoint, json=payload, headers=headers) 498 | last_request = time.time() 499 | break 500 | except Exception as e: 501 | print("_request() exception: ", e) 502 | time.sleep(1) 503 | if tries > 3: 504 | print("Request failed. Quit!") 505 | break 506 | finally: 507 | LOCK = False 508 | return response 509 | 510 | def post(self, endpoint, payload, login=False): 511 | url = self.api_url 512 | if not login: 513 | checker = self.make_checker(endpoint, payload) 514 | headers = {"APIKEY": self.api_key, 515 | "Checker": checker, 516 | "Authorization": self.hash 517 | } 518 | else: 519 | headers = {"APIKEY": self.api_key} 520 | resp = self._request("POST", url, endpoint, payload=payload, headers=headers) 521 | return resp 522 | 523 | is_alive = property(get_is_alive) 524 | logged_in = property(get_logged_in) --------------------------------------------------------------------------------