bitunix-automated-crypto-trading 2.6.7__py3-none-any.whl → 2.6.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bitunix_automated_crypto_trading/AsyncThreadRunner.py +81 -81
- bitunix_automated_crypto_trading/BitunixApi.py +278 -278
- bitunix_automated_crypto_trading/BitunixSignal.py +1099 -1099
- bitunix_automated_crypto_trading/BitunixWebSocket.py +254 -254
- bitunix_automated_crypto_trading/DataFrameHtmlRenderer.py +74 -74
- bitunix_automated_crypto_trading/NotificationManager.py +23 -23
- bitunix_automated_crypto_trading/ThreadManager.py +68 -68
- bitunix_automated_crypto_trading/TickerManager.py +635 -635
- bitunix_automated_crypto_trading/bitunix.py +597 -594
- bitunix_automated_crypto_trading/config.py +90 -90
- bitunix_automated_crypto_trading/logger.py +84 -84
- {bitunix_automated_crypto_trading-2.6.7.dist-info → bitunix_automated_crypto_trading-2.6.8.dist-info}/METADATA +36 -36
- bitunix_automated_crypto_trading-2.6.8.dist-info/RECORD +17 -0
- bitunix_automated_crypto_trading/config.txt +0 -60
- bitunix_automated_crypto_trading/sampleenv.txt +0 -5
- bitunix_automated_crypto_trading/static/chart.css +0 -28
- bitunix_automated_crypto_trading/static/chart.js +0 -362
- bitunix_automated_crypto_trading/static/modal.css +0 -68
- bitunix_automated_crypto_trading/static/modal.js +0 -147
- bitunix_automated_crypto_trading/static/script.js +0 -166
- bitunix_automated_crypto_trading/static/styles.css +0 -118
- bitunix_automated_crypto_trading/templates/charts.html +0 -98
- bitunix_automated_crypto_trading/templates/login.html +0 -19
- bitunix_automated_crypto_trading/templates/main.html +0 -551
- bitunix_automated_crypto_trading/templates/modal-chart.html +0 -26
- bitunix_automated_crypto_trading/templates/modal-config.html +0 -34
- bitunix_automated_crypto_trading/templates/modal-logs.html +0 -15
- bitunix_automated_crypto_trading-2.6.7.dist-info/RECORD +0 -31
- {bitunix_automated_crypto_trading-2.6.7.dist-info → bitunix_automated_crypto_trading-2.6.8.dist-info}/WHEEL +0 -0
- {bitunix_automated_crypto_trading-2.6.7.dist-info → bitunix_automated_crypto_trading-2.6.8.dist-info}/entry_points.txt +0 -0
- {bitunix_automated_crypto_trading-2.6.7.dist-info → bitunix_automated_crypto_trading-2.6.8.dist-info}/top_level.txt +0 -0
@@ -1,278 +1,278 @@
|
|
1
|
-
import secrets
|
2
|
-
import base64
|
3
|
-
import time
|
4
|
-
import json
|
5
|
-
import hashlib
|
6
|
-
import asyncio
|
7
|
-
import requests
|
8
|
-
from urllib.parse import urlencode
|
9
|
-
from typing import Dict, Any
|
10
|
-
import traceback
|
11
|
-
from
|
12
|
-
logger = Logger(__name__).get_logger()
|
13
|
-
|
14
|
-
|
15
|
-
class BitunixApi:
|
16
|
-
|
17
|
-
def __init__(self, api_key, secret_key, settings):
|
18
|
-
self.api_key = api_key
|
19
|
-
self.secret_key = secret_key
|
20
|
-
|
21
|
-
self.session = requests.Session()
|
22
|
-
self.session.headers.update({
|
23
|
-
'Content-Type': 'application/json',
|
24
|
-
'User-Agent': 'BitunixAPI/1.0'
|
25
|
-
})
|
26
|
-
|
27
|
-
self.pending_positions_URL="https://fapi.bitunix.com/api/v1/futures/position/get_pending_positions"
|
28
|
-
self.account_Url="https://fapi.bitunix.com/api/v1/futures/account"
|
29
|
-
self.ticker_Url='https://fapi.bitunix.com/api/v1/futures/market/tickers'
|
30
|
-
self.ticker_pair_Url='https://fapi.bitunix.com/api/v1/futures/market/trading_pairs'
|
31
|
-
self.kline_Url='https://fapi.bitunix.com/api/v1/futures/market/kline'
|
32
|
-
self.depth_Url='https://fapi.bitunix.com/api/v1/futures/market/depth'
|
33
|
-
self.placeOrder_Url="https://fapi.bitunix.com/api/v1/futures/trade/place_order"
|
34
|
-
self.flashClose_Url="https://fapi.bitunix.com/api/v1/futures/trade/flash_close_position"
|
35
|
-
self.pending_order_url="https://fapi.bitunix.com/api/v1/futures/trade/get_pending_orders"
|
36
|
-
self.cancelOrder_Url="https://fapi.bitunix.com/api/v1/futures/trade/cancel_orders"
|
37
|
-
self.Trade_history_Url="https://fapi.bitunix.com/api/v1/futures/trade/get_history_trades"
|
38
|
-
self.position_history_Url="https://fapi.bitunix.com/api/v1/futures/position/get_history_positions"
|
39
|
-
|
40
|
-
async def update_settings(self, settings):
|
41
|
-
self.settings = settings
|
42
|
-
|
43
|
-
async def create_timestamp(self):
|
44
|
-
return str(int(time.time()*1000))
|
45
|
-
|
46
|
-
async def is_near_high_of_day(self, current_value, high_of_day, threshold_percentage=5):
|
47
|
-
# Calculate the difference as a percentage of the high of the day
|
48
|
-
difference_percentage = ((high_of_day - current_value) / high_of_day) * 100
|
49
|
-
# Check if the difference is within the threshold
|
50
|
-
return difference_percentage <= threshold_percentage
|
51
|
-
|
52
|
-
async def is_near_low_of_day(self, current_value, low_of_day, threshold_percentage=5):
|
53
|
-
# Calculate the difference as a percentage of the low of the day
|
54
|
-
difference_percentage = ((current_value - low_of_day) / low_of_day) * 100
|
55
|
-
# Check if the difference is within the threshold
|
56
|
-
return difference_percentage <= threshold_percentage
|
57
|
-
|
58
|
-
|
59
|
-
async def _generate_nonce(self) -> str:
|
60
|
-
random_bytes = secrets.token_bytes(32)
|
61
|
-
return base64.b64encode(random_bytes).decode('utf-8')
|
62
|
-
|
63
|
-
|
64
|
-
async def sign_request(self, nonce: str, timestamp: str,
|
65
|
-
query_params: str = None,
|
66
|
-
body: str = None) -> str:
|
67
|
-
query_string = query_params if query_params else ""
|
68
|
-
body_string = body if body else ""
|
69
|
-
message = f"{nonce}{timestamp}{self.api_key}{query_string}{body_string}"
|
70
|
-
|
71
|
-
# First SHA256 encryption
|
72
|
-
digest = hashlib.sha256(message.encode()).hexdigest()
|
73
|
-
|
74
|
-
# Second SHA256 encryption
|
75
|
-
sign = hashlib.sha256((digest + self.secret_key).encode()).hexdigest()
|
76
|
-
|
77
|
-
return sign
|
78
|
-
|
79
|
-
async def _get(self, endpoint: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
|
80
|
-
response = self.session.get(endpoint, params=params)
|
81
|
-
response.raise_for_status()
|
82
|
-
return response.json()
|
83
|
-
|
84
|
-
async def _get_authenticated(self, endpoint: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
|
85
|
-
timestamp = await self.create_timestamp()
|
86
|
-
nonce = await self._generate_nonce()
|
87
|
-
|
88
|
-
headers = {
|
89
|
-
"api-key": self.api_key,
|
90
|
-
"timestamp": timestamp,
|
91
|
-
"nonce": nonce,
|
92
|
-
}
|
93
|
-
|
94
|
-
query_string = urlencode(sorted(params.items())).replace('=','') if params else ""
|
95
|
-
signature = await self.sign_request(nonce, timestamp, query_params=query_string)
|
96
|
-
headers["sign"] = signature
|
97
|
-
|
98
|
-
response = self.session.get(endpoint, params=params, headers=headers)
|
99
|
-
response.raise_for_status()
|
100
|
-
return response.json()
|
101
|
-
|
102
|
-
async def _post_authenticated(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
103
|
-
timestamp = await self.create_timestamp()
|
104
|
-
nonce = await self._generate_nonce()
|
105
|
-
|
106
|
-
headers = {
|
107
|
-
"api-key": self.api_key,
|
108
|
-
"timestamp": timestamp,
|
109
|
-
"nonce": nonce,
|
110
|
-
"Content-Type": "application/json"
|
111
|
-
}
|
112
|
-
|
113
|
-
body_string = json.dumps(data, separators=(',', ':'))
|
114
|
-
signature = await self.sign_request(nonce, timestamp, body=body_string)
|
115
|
-
headers["sign"] = signature
|
116
|
-
|
117
|
-
response = self.session.post(endpoint, data=body_string, headers=headers)
|
118
|
-
logger.info(f"Response: {body_string} {response.json()}")
|
119
|
-
response.raise_for_status()
|
120
|
-
return response.json()
|
121
|
-
|
122
|
-
async def PlaceOrder(self, ticker, qty, price, side, positionId=0, tradeSide="OPEN",reduceOnly=False):
|
123
|
-
data = {
|
124
|
-
"side": side,
|
125
|
-
"orderType":"LIMIT",
|
126
|
-
"qty": qty,
|
127
|
-
"price": price,
|
128
|
-
"symbol": ticker,
|
129
|
-
"tradeSide":tradeSide,
|
130
|
-
"reduceOnly":reduceOnly,
|
131
|
-
"positionId":positionId
|
132
|
-
}
|
133
|
-
datajs = await self._post_authenticated(self.placeOrder_Url,data)
|
134
|
-
return datajs
|
135
|
-
|
136
|
-
async def FlashClose(self, positionId):
|
137
|
-
data = {
|
138
|
-
"positionId": positionId
|
139
|
-
}
|
140
|
-
datajs = await self._post_authenticated(self.flashClose_Url,data)
|
141
|
-
return datajs
|
142
|
-
|
143
|
-
async def CancelOrder(self, symbol, orderId):
|
144
|
-
data = {
|
145
|
-
"symbol": symbol,
|
146
|
-
"orderList":[{"orderId": orderId}]
|
147
|
-
}
|
148
|
-
datajs = await self._post_authenticated(self.cancelOrder_Url,data)
|
149
|
-
return datajs
|
150
|
-
|
151
|
-
async def GetTradeHistoryData(self):
|
152
|
-
tradeHistory=await self._get_authenticated(self.Trade_history_Url)
|
153
|
-
if tradeHistory['code']==0:
|
154
|
-
return tradeHistory['data']
|
155
|
-
else:
|
156
|
-
logger.info(tradeHistory['msg'])
|
157
|
-
|
158
|
-
async def GetPendingOrderData(self,dictparm={}):
|
159
|
-
orders=await self._get_authenticated(self.pending_order_url, dictparm)
|
160
|
-
if orders['code']==0:
|
161
|
-
return orders['data']
|
162
|
-
else:
|
163
|
-
logger.info(orders['msg'])
|
164
|
-
|
165
|
-
async def GetPendingPositionData(self, dictparm={}):
|
166
|
-
positions=await self._get_authenticated(self.pending_positions_URL, dictparm)
|
167
|
-
if positions['code']==0:
|
168
|
-
return positions['data']
|
169
|
-
else:
|
170
|
-
logger.info(positions['msg'])
|
171
|
-
|
172
|
-
async def GetPositionHistoryData(self, dictparm={}):
|
173
|
-
tradeHistory=await self._get_authenticated(self.position_history_Url, dictparm)
|
174
|
-
if tradeHistory['code']==0:
|
175
|
-
return tradeHistory['data']
|
176
|
-
else:
|
177
|
-
logger.info(tradeHistory['msg'])
|
178
|
-
|
179
|
-
|
180
|
-
async def GetportfolioData(self):
|
181
|
-
portfolio=await self._get_authenticated(self.account_Url, params={"marginCoin":"USDT"})
|
182
|
-
if portfolio['code']==0:
|
183
|
-
return portfolio['data']
|
184
|
-
else:
|
185
|
-
logger.info(portfolio['msg'])
|
186
|
-
|
187
|
-
|
188
|
-
async def GetTickerslastPrice(self, tickersStr):
|
189
|
-
try:
|
190
|
-
resp = self.session.get(self.ticker_Url+'?symbols='+tickersStr)
|
191
|
-
datajs = resp.json()
|
192
|
-
if datajs['code']==0:
|
193
|
-
return datajs['data']
|
194
|
-
except Exception as e:
|
195
|
-
stack = traceback.extract_stack()
|
196
|
-
function_name = stack[-2].name
|
197
|
-
logger.error(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
198
|
-
|
199
|
-
async def GetTickersPair(self, tickersStr):
|
200
|
-
try:
|
201
|
-
resp = self.session.get(self.ticker_pair_Url+'?symbols='+tickersStr)
|
202
|
-
datajs = resp.json()
|
203
|
-
if datajs['code']==0:
|
204
|
-
return datajs['data']
|
205
|
-
except Exception as e:
|
206
|
-
stack = traceback.extract_stack()
|
207
|
-
function_name = stack[-2].name
|
208
|
-
logger.error(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
209
|
-
|
210
|
-
async def GetTickerList(self, threshold, volume):
|
211
|
-
symbols=[]
|
212
|
-
try:
|
213
|
-
resp = self.session.get(self.ticker_Url)
|
214
|
-
datajs = resp.json()
|
215
|
-
for item in datajs["data"]:
|
216
|
-
if await self.is_near_high_of_day(float(item['last']), float(item['high']) ,threshold) and float(item['baseVol']) > volume:
|
217
|
-
symbols.append(item['symbol'])
|
218
|
-
if await self.is_near_low_of_day(float(item['last']), float(item['low']) ,threshold) and float(item['baseVol']) > volume:
|
219
|
-
symbols.append(item['symbol'])
|
220
|
-
#if float(item['baseVol']) > volume:
|
221
|
-
# symbols.append(item['symbol'])
|
222
|
-
return symbols
|
223
|
-
except Exception as e:
|
224
|
-
stack = traceback.extract_stack()
|
225
|
-
function_name = stack[-2].name
|
226
|
-
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
227
|
-
|
228
|
-
async def GetTickerData(self):
|
229
|
-
try:
|
230
|
-
url = f'{self.ticker_Url}'
|
231
|
-
resp = self.session.get(url)
|
232
|
-
datajs = resp.json()
|
233
|
-
if datajs['code']==0:
|
234
|
-
return datajs['data']
|
235
|
-
except Exception as e:
|
236
|
-
stack = traceback.extract_stack()
|
237
|
-
function_name = stack[-2].name
|
238
|
-
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
239
|
-
|
240
|
-
async def GetDepthData(self,symbol,limit):
|
241
|
-
try:
|
242
|
-
url = f'{self.depth_Url}?symbol={symbol}&limit={limit}'
|
243
|
-
resp = self.session.get(url)
|
244
|
-
datajs = resp.json()
|
245
|
-
if datajs['code']==0:
|
246
|
-
return datajs['data']
|
247
|
-
except Exception as e:
|
248
|
-
stack = traceback.extract_stack()
|
249
|
-
function_name = stack[-2].name
|
250
|
-
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
251
|
-
|
252
|
-
async def GetKlineHistory(self, ticker, interval, limit):
|
253
|
-
data = []
|
254
|
-
lm=limit
|
255
|
-
current_unix_timestamp = int(time.time())
|
256
|
-
try:
|
257
|
-
while True:
|
258
|
-
url = f'{self.kline_Url}?symbol={ticker}&startTime={current_unix_timestamp}&interval={interval}&limit={lm}'
|
259
|
-
resp = self.session.get(url)
|
260
|
-
datajs = resp.json()
|
261
|
-
if len(datajs['data']) > 0:
|
262
|
-
current_unix_timestamp = str(int(datajs['data'][-1]['time']) + 1) # Adjust 'time' to match the appropriate key in your data
|
263
|
-
data.extend(datajs['data'])
|
264
|
-
lm=limit-len(data)
|
265
|
-
if len(data) >= limit:
|
266
|
-
break
|
267
|
-
else:
|
268
|
-
break
|
269
|
-
return data
|
270
|
-
except Exception as e:
|
271
|
-
stack = traceback.extract_stack()
|
272
|
-
function_name = stack[-2].name
|
273
|
-
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
274
|
-
|
275
|
-
def __del__(self):
|
276
|
-
"""Cleanup method to close the session"""
|
277
|
-
if hasattr(self, 'session'):
|
278
|
-
self.session.close()
|
1
|
+
import secrets
|
2
|
+
import base64
|
3
|
+
import time
|
4
|
+
import json
|
5
|
+
import hashlib
|
6
|
+
import asyncio
|
7
|
+
import requests
|
8
|
+
from urllib.parse import urlencode
|
9
|
+
from typing import Dict, Any
|
10
|
+
import traceback
|
11
|
+
from logger import Logger
|
12
|
+
logger = Logger(__name__).get_logger()
|
13
|
+
|
14
|
+
|
15
|
+
class BitunixApi:
|
16
|
+
|
17
|
+
def __init__(self, api_key, secret_key, settings):
|
18
|
+
self.api_key = api_key
|
19
|
+
self.secret_key = secret_key
|
20
|
+
|
21
|
+
self.session = requests.Session()
|
22
|
+
self.session.headers.update({
|
23
|
+
'Content-Type': 'application/json',
|
24
|
+
'User-Agent': 'BitunixAPI/1.0'
|
25
|
+
})
|
26
|
+
|
27
|
+
self.pending_positions_URL="https://fapi.bitunix.com/api/v1/futures/position/get_pending_positions"
|
28
|
+
self.account_Url="https://fapi.bitunix.com/api/v1/futures/account"
|
29
|
+
self.ticker_Url='https://fapi.bitunix.com/api/v1/futures/market/tickers'
|
30
|
+
self.ticker_pair_Url='https://fapi.bitunix.com/api/v1/futures/market/trading_pairs'
|
31
|
+
self.kline_Url='https://fapi.bitunix.com/api/v1/futures/market/kline'
|
32
|
+
self.depth_Url='https://fapi.bitunix.com/api/v1/futures/market/depth'
|
33
|
+
self.placeOrder_Url="https://fapi.bitunix.com/api/v1/futures/trade/place_order"
|
34
|
+
self.flashClose_Url="https://fapi.bitunix.com/api/v1/futures/trade/flash_close_position"
|
35
|
+
self.pending_order_url="https://fapi.bitunix.com/api/v1/futures/trade/get_pending_orders"
|
36
|
+
self.cancelOrder_Url="https://fapi.bitunix.com/api/v1/futures/trade/cancel_orders"
|
37
|
+
self.Trade_history_Url="https://fapi.bitunix.com/api/v1/futures/trade/get_history_trades"
|
38
|
+
self.position_history_Url="https://fapi.bitunix.com/api/v1/futures/position/get_history_positions"
|
39
|
+
|
40
|
+
async def update_settings(self, settings):
|
41
|
+
self.settings = settings
|
42
|
+
|
43
|
+
async def create_timestamp(self):
|
44
|
+
return str(int(time.time()*1000))
|
45
|
+
|
46
|
+
async def is_near_high_of_day(self, current_value, high_of_day, threshold_percentage=5):
|
47
|
+
# Calculate the difference as a percentage of the high of the day
|
48
|
+
difference_percentage = ((high_of_day - current_value) / high_of_day) * 100
|
49
|
+
# Check if the difference is within the threshold
|
50
|
+
return difference_percentage <= threshold_percentage
|
51
|
+
|
52
|
+
async def is_near_low_of_day(self, current_value, low_of_day, threshold_percentage=5):
|
53
|
+
# Calculate the difference as a percentage of the low of the day
|
54
|
+
difference_percentage = ((current_value - low_of_day) / low_of_day) * 100
|
55
|
+
# Check if the difference is within the threshold
|
56
|
+
return difference_percentage <= threshold_percentage
|
57
|
+
|
58
|
+
|
59
|
+
async def _generate_nonce(self) -> str:
|
60
|
+
random_bytes = secrets.token_bytes(32)
|
61
|
+
return base64.b64encode(random_bytes).decode('utf-8')
|
62
|
+
|
63
|
+
|
64
|
+
async def sign_request(self, nonce: str, timestamp: str,
|
65
|
+
query_params: str = None,
|
66
|
+
body: str = None) -> str:
|
67
|
+
query_string = query_params if query_params else ""
|
68
|
+
body_string = body if body else ""
|
69
|
+
message = f"{nonce}{timestamp}{self.api_key}{query_string}{body_string}"
|
70
|
+
|
71
|
+
# First SHA256 encryption
|
72
|
+
digest = hashlib.sha256(message.encode()).hexdigest()
|
73
|
+
|
74
|
+
# Second SHA256 encryption
|
75
|
+
sign = hashlib.sha256((digest + self.secret_key).encode()).hexdigest()
|
76
|
+
|
77
|
+
return sign
|
78
|
+
|
79
|
+
async def _get(self, endpoint: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
|
80
|
+
response = self.session.get(endpoint, params=params)
|
81
|
+
response.raise_for_status()
|
82
|
+
return response.json()
|
83
|
+
|
84
|
+
async def _get_authenticated(self, endpoint: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
|
85
|
+
timestamp = await self.create_timestamp()
|
86
|
+
nonce = await self._generate_nonce()
|
87
|
+
|
88
|
+
headers = {
|
89
|
+
"api-key": self.api_key,
|
90
|
+
"timestamp": timestamp,
|
91
|
+
"nonce": nonce,
|
92
|
+
}
|
93
|
+
|
94
|
+
query_string = urlencode(sorted(params.items())).replace('=','') if params else ""
|
95
|
+
signature = await self.sign_request(nonce, timestamp, query_params=query_string)
|
96
|
+
headers["sign"] = signature
|
97
|
+
|
98
|
+
response = self.session.get(endpoint, params=params, headers=headers)
|
99
|
+
response.raise_for_status()
|
100
|
+
return response.json()
|
101
|
+
|
102
|
+
async def _post_authenticated(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
|
103
|
+
timestamp = await self.create_timestamp()
|
104
|
+
nonce = await self._generate_nonce()
|
105
|
+
|
106
|
+
headers = {
|
107
|
+
"api-key": self.api_key,
|
108
|
+
"timestamp": timestamp,
|
109
|
+
"nonce": nonce,
|
110
|
+
"Content-Type": "application/json"
|
111
|
+
}
|
112
|
+
|
113
|
+
body_string = json.dumps(data, separators=(',', ':'))
|
114
|
+
signature = await self.sign_request(nonce, timestamp, body=body_string)
|
115
|
+
headers["sign"] = signature
|
116
|
+
|
117
|
+
response = self.session.post(endpoint, data=body_string, headers=headers)
|
118
|
+
logger.info(f"Response: {body_string} {response.json()}")
|
119
|
+
response.raise_for_status()
|
120
|
+
return response.json()
|
121
|
+
|
122
|
+
async def PlaceOrder(self, ticker, qty, price, side, positionId=0, tradeSide="OPEN",reduceOnly=False):
|
123
|
+
data = {
|
124
|
+
"side": side,
|
125
|
+
"orderType":"LIMIT",
|
126
|
+
"qty": qty,
|
127
|
+
"price": price,
|
128
|
+
"symbol": ticker,
|
129
|
+
"tradeSide":tradeSide,
|
130
|
+
"reduceOnly":reduceOnly,
|
131
|
+
"positionId":positionId
|
132
|
+
}
|
133
|
+
datajs = await self._post_authenticated(self.placeOrder_Url,data)
|
134
|
+
return datajs
|
135
|
+
|
136
|
+
async def FlashClose(self, positionId):
|
137
|
+
data = {
|
138
|
+
"positionId": positionId
|
139
|
+
}
|
140
|
+
datajs = await self._post_authenticated(self.flashClose_Url,data)
|
141
|
+
return datajs
|
142
|
+
|
143
|
+
async def CancelOrder(self, symbol, orderId):
|
144
|
+
data = {
|
145
|
+
"symbol": symbol,
|
146
|
+
"orderList":[{"orderId": orderId}]
|
147
|
+
}
|
148
|
+
datajs = await self._post_authenticated(self.cancelOrder_Url,data)
|
149
|
+
return datajs
|
150
|
+
|
151
|
+
async def GetTradeHistoryData(self):
|
152
|
+
tradeHistory=await self._get_authenticated(self.Trade_history_Url)
|
153
|
+
if tradeHistory['code']==0:
|
154
|
+
return tradeHistory['data']
|
155
|
+
else:
|
156
|
+
logger.info(tradeHistory['msg'])
|
157
|
+
|
158
|
+
async def GetPendingOrderData(self,dictparm={}):
|
159
|
+
orders=await self._get_authenticated(self.pending_order_url, dictparm)
|
160
|
+
if orders['code']==0:
|
161
|
+
return orders['data']
|
162
|
+
else:
|
163
|
+
logger.info(orders['msg'])
|
164
|
+
|
165
|
+
async def GetPendingPositionData(self, dictparm={}):
|
166
|
+
positions=await self._get_authenticated(self.pending_positions_URL, dictparm)
|
167
|
+
if positions['code']==0:
|
168
|
+
return positions['data']
|
169
|
+
else:
|
170
|
+
logger.info(positions['msg'])
|
171
|
+
|
172
|
+
async def GetPositionHistoryData(self, dictparm={}):
|
173
|
+
tradeHistory=await self._get_authenticated(self.position_history_Url, dictparm)
|
174
|
+
if tradeHistory['code']==0:
|
175
|
+
return tradeHistory['data']
|
176
|
+
else:
|
177
|
+
logger.info(tradeHistory['msg'])
|
178
|
+
|
179
|
+
|
180
|
+
async def GetportfolioData(self):
|
181
|
+
portfolio=await self._get_authenticated(self.account_Url, params={"marginCoin":"USDT"})
|
182
|
+
if portfolio['code']==0:
|
183
|
+
return portfolio['data']
|
184
|
+
else:
|
185
|
+
logger.info(portfolio['msg'])
|
186
|
+
|
187
|
+
|
188
|
+
async def GetTickerslastPrice(self, tickersStr):
|
189
|
+
try:
|
190
|
+
resp = self.session.get(self.ticker_Url+'?symbols='+tickersStr)
|
191
|
+
datajs = resp.json()
|
192
|
+
if datajs['code']==0:
|
193
|
+
return datajs['data']
|
194
|
+
except Exception as e:
|
195
|
+
stack = traceback.extract_stack()
|
196
|
+
function_name = stack[-2].name
|
197
|
+
logger.error(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
198
|
+
|
199
|
+
async def GetTickersPair(self, tickersStr):
|
200
|
+
try:
|
201
|
+
resp = self.session.get(self.ticker_pair_Url+'?symbols='+tickersStr)
|
202
|
+
datajs = resp.json()
|
203
|
+
if datajs['code']==0:
|
204
|
+
return datajs['data']
|
205
|
+
except Exception as e:
|
206
|
+
stack = traceback.extract_stack()
|
207
|
+
function_name = stack[-2].name
|
208
|
+
logger.error(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
209
|
+
|
210
|
+
async def GetTickerList(self, threshold, volume):
|
211
|
+
symbols=[]
|
212
|
+
try:
|
213
|
+
resp = self.session.get(self.ticker_Url)
|
214
|
+
datajs = resp.json()
|
215
|
+
for item in datajs["data"]:
|
216
|
+
if await self.is_near_high_of_day(float(item['last']), float(item['high']) ,threshold) and float(item['baseVol']) > volume:
|
217
|
+
symbols.append(item['symbol'])
|
218
|
+
if await self.is_near_low_of_day(float(item['last']), float(item['low']) ,threshold) and float(item['baseVol']) > volume:
|
219
|
+
symbols.append(item['symbol'])
|
220
|
+
#if float(item['baseVol']) > volume:
|
221
|
+
# symbols.append(item['symbol'])
|
222
|
+
return symbols
|
223
|
+
except Exception as e:
|
224
|
+
stack = traceback.extract_stack()
|
225
|
+
function_name = stack[-2].name
|
226
|
+
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
227
|
+
|
228
|
+
async def GetTickerData(self):
|
229
|
+
try:
|
230
|
+
url = f'{self.ticker_Url}'
|
231
|
+
resp = self.session.get(url)
|
232
|
+
datajs = resp.json()
|
233
|
+
if datajs['code']==0:
|
234
|
+
return datajs['data']
|
235
|
+
except Exception as e:
|
236
|
+
stack = traceback.extract_stack()
|
237
|
+
function_name = stack[-2].name
|
238
|
+
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
239
|
+
|
240
|
+
async def GetDepthData(self,symbol,limit):
|
241
|
+
try:
|
242
|
+
url = f'{self.depth_Url}?symbol={symbol}&limit={limit}'
|
243
|
+
resp = self.session.get(url)
|
244
|
+
datajs = resp.json()
|
245
|
+
if datajs['code']==0:
|
246
|
+
return datajs['data']
|
247
|
+
except Exception as e:
|
248
|
+
stack = traceback.extract_stack()
|
249
|
+
function_name = stack[-2].name
|
250
|
+
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
251
|
+
|
252
|
+
async def GetKlineHistory(self, ticker, interval, limit):
|
253
|
+
data = []
|
254
|
+
lm=limit
|
255
|
+
current_unix_timestamp = int(time.time())
|
256
|
+
try:
|
257
|
+
while True:
|
258
|
+
url = f'{self.kline_Url}?symbol={ticker}&startTime={current_unix_timestamp}&interval={interval}&limit={lm}'
|
259
|
+
resp = self.session.get(url)
|
260
|
+
datajs = resp.json()
|
261
|
+
if len(datajs['data']) > 0:
|
262
|
+
current_unix_timestamp = str(int(datajs['data'][-1]['time']) + 1) # Adjust 'time' to match the appropriate key in your data
|
263
|
+
data.extend(datajs['data'])
|
264
|
+
lm=limit-len(data)
|
265
|
+
if len(data) >= limit:
|
266
|
+
break
|
267
|
+
else:
|
268
|
+
break
|
269
|
+
return data
|
270
|
+
except Exception as e:
|
271
|
+
stack = traceback.extract_stack()
|
272
|
+
function_name = stack[-2].name
|
273
|
+
logger.info(f"Function: {function_name}, {e}, {e.args}, {type(e).__name__}")
|
274
|
+
|
275
|
+
def __del__(self):
|
276
|
+
"""Cleanup method to close the session"""
|
277
|
+
if hasattr(self, 'session'):
|
278
|
+
self.session.close()
|