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,551 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
|
5
|
-
<meta charset="UTF-8">
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
-
<title>Bitunix Auto Trading</title>
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
9
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-chart-financial"></script>
|
10
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
|
11
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
|
12
|
-
<link rel="stylesheet" href="static/styles.css">
|
13
|
-
<link rel="stylesheet" href="static/modal.css">
|
14
|
-
<link rel="stylesheet" href="static/chart.css">
|
15
|
-
<style>
|
16
|
-
|
17
|
-
.mainbody {
|
18
|
-
flex: 1;
|
19
|
-
margin-top: 1px; /* Adjust this value according to the height of your header */
|
20
|
-
margin-bottom: 60px; /* Adjust this value according to the height of your footer */
|
21
|
-
overflow-y: auto;
|
22
|
-
padding: 1em;
|
23
|
-
}
|
24
|
-
</style>
|
25
|
-
</head>
|
26
|
-
<body>
|
27
|
-
<div class="mainbody">
|
28
|
-
<div class="row">
|
29
|
-
<div id="portfolio">
|
30
|
-
Loading portfolio value...
|
31
|
-
</div>
|
32
|
-
</div>
|
33
|
-
<div class="container">
|
34
|
-
<div class="right">
|
35
|
-
<label for="optionMovingAverage">Moving Average</label>
|
36
|
-
<select disabled id="optionMovingAverage">
|
37
|
-
<option value="1d">Daily</option>
|
38
|
-
<option value="1h">Hourly</option>
|
39
|
-
<option value="15m">15 minutes</option>
|
40
|
-
<option value="5m">5 minutes</option>
|
41
|
-
<option value="1m">1 minutes</option>
|
42
|
-
</select>
|
43
|
-
</div>
|
44
|
-
<div class="right">
|
45
|
-
<label for="maxAutoTrades">MaxAutoTrades</label>
|
46
|
-
<input disabled type="text" id="maxAutoTrades">
|
47
|
-
</div>
|
48
|
-
<div class="right">
|
49
|
-
<label for="autoTrade">AutoTrade</label>
|
50
|
-
<input disabled type="checkbox" id="autoTrade" name="AutoTrade">
|
51
|
-
</div>
|
52
|
-
<div class="right">
|
53
|
-
<label for="totalProfit">Total Profit</label>
|
54
|
-
<div id="totalProfit">...</div>
|
55
|
-
</div>
|
56
|
-
<div class="left">
|
57
|
-
<label for="tickerDataCycleTime">Ticker Data Last Cycle</label>
|
58
|
-
<div id="tickerDataCycleTime">...</div>
|
59
|
-
</div>
|
60
|
-
<div class="left">
|
61
|
-
<label for="autoTradeCycleTime">AutoTrade Last Cycle</label>
|
62
|
-
<div id="autoTradeCycleTime">...</div>
|
63
|
-
</div>
|
64
|
-
<div class="right">
|
65
|
-
<button id="config">Config</button>
|
66
|
-
</div>
|
67
|
-
</div>
|
68
|
-
|
69
|
-
<div id="modal-container-wrapper"></div>
|
70
|
-
|
71
|
-
<span>Positions</span>
|
72
|
-
<div class="row">
|
73
|
-
<div id="positions">
|
74
|
-
Loading positions...
|
75
|
-
</div>
|
76
|
-
</div>
|
77
|
-
<span>orders</span>
|
78
|
-
<div class="row">
|
79
|
-
<div id="orders">
|
80
|
-
Loading orders...
|
81
|
-
</div>
|
82
|
-
</div>
|
83
|
-
<span>selected signals</span>
|
84
|
-
<div class="row">
|
85
|
-
<div id="signals">
|
86
|
-
Loading signals...
|
87
|
-
</div>
|
88
|
-
</div>
|
89
|
-
<span>all signals</span>
|
90
|
-
<div class="row">
|
91
|
-
<div id="study">
|
92
|
-
Loading signals...
|
93
|
-
</div>
|
94
|
-
</div>
|
95
|
-
<span>positionHistory</span>
|
96
|
-
<div class="row">
|
97
|
-
<div id="positionHistory">
|
98
|
-
Loading positionHistory...
|
99
|
-
</div>
|
100
|
-
</div>
|
101
|
-
</div>
|
102
|
-
<footer>
|
103
|
-
<div class="dropdown">
|
104
|
-
<!-- <div id="message" class="message" onclick="toggleDropdown()"></div> -->
|
105
|
-
<div id="message" class="message"></div>
|
106
|
-
<div id="dropdown-content" class="dropdown-content">
|
107
|
-
<!-- Additional messages will be inserted here -->
|
108
|
-
</div>
|
109
|
-
</div>
|
110
|
-
</footer>
|
111
|
-
|
112
|
-
<script src="/static/modal.js"></script>
|
113
|
-
<script src="/static/script.js"></script>
|
114
|
-
<script src="/static/chart.js"></script>
|
115
|
-
<script>
|
116
|
-
|
117
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
118
|
-
//display the main screen with portfoio, positions, order, signals, positionhistory
|
119
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
120
|
-
|
121
|
-
const host = window.location.hostname;
|
122
|
-
const websocket_m = new WebSocket(`ws://${host}:8000/wsmain`);
|
123
|
-
websocket_m.onopen = function() {
|
124
|
-
document.getElementById('message').innerHTML = "main page webSocket connection opened"
|
125
|
-
//Send a ping every 30 seconds
|
126
|
-
setInterval(()=>{
|
127
|
-
if (websocket_m.readyState === WebSocket.OPEN) {
|
128
|
-
websocket_m.send("ping");
|
129
|
-
}
|
130
|
-
}, 30000);
|
131
|
-
}
|
132
|
-
|
133
|
-
websocket_m.onmessage = function(event) {
|
134
|
-
if (event.data === "pong") {
|
135
|
-
return;
|
136
|
-
}
|
137
|
-
|
138
|
-
const messageElement = JSON.parse(event.data);
|
139
|
-
document.getElementById("portfolio").innerHTML = messageElement.dataframes.portfolio;
|
140
|
-
document.getElementById("positions").innerHTML = messageElement.dataframes.positions;
|
141
|
-
document.getElementById("orders").innerHTML = messageElement.dataframes.orders;
|
142
|
-
document.getElementById("signals").innerHTML = messageElement.dataframes.signals;
|
143
|
-
document.getElementById("study").innerHTML = messageElement.dataframes.study;
|
144
|
-
document.getElementById("positionHistory").innerHTML = messageElement.dataframes.positionHistory;
|
145
|
-
document.getElementById('message').innerHTML = messageElement.status_messages;
|
146
|
-
|
147
|
-
document.getElementById('totalProfit').innerText = messageElement.profit;
|
148
|
-
document.getElementById("autoTradeCycleTime").innerText = messageElement.atctime;
|
149
|
-
document.getElementById("tickerDataCycleTime").innerText = messageElement.tdctime;
|
150
|
-
const messages = messageElement.status_messages;
|
151
|
-
displayNotifications(messages)
|
152
|
-
|
153
|
-
const currentTime = new Date();
|
154
|
-
if (messageElement.atctime) {
|
155
|
-
const atctime = new Date(messageElement.atctime);
|
156
|
-
const atctime1 = Math.abs(currentTime - atctime) / (1000 * 60);
|
157
|
-
if (atctime1 > 5) {
|
158
|
-
document.getElementById("autoTradeCycleTime").style.color = "red";
|
159
|
-
} else {
|
160
|
-
document.getElementById("autoTradeCycleTime").style.color = "black";
|
161
|
-
}
|
162
|
-
}
|
163
|
-
if (messageElement.tdctime) {
|
164
|
-
const tdctime = new Date(messageElement.tdctime);
|
165
|
-
const tdctime1 = Math.abs(currentTime - tdctime) / (1000 * 60);
|
166
|
-
if (tdctime1 > 5) {
|
167
|
-
document.getElementById("tickerDataCycleTime").style.color = "red";
|
168
|
-
} else {
|
169
|
-
document.getElementById("tickerDataCycleTime").style.color = "black";
|
170
|
-
}
|
171
|
-
}
|
172
|
-
};
|
173
|
-
|
174
|
-
|
175
|
-
websocket_m.onerror = function(error) {
|
176
|
-
document.getElementById('message').innerHTML = "main page webSocket connection failed.";
|
177
|
-
};
|
178
|
-
|
179
|
-
websocket_m.onclose = function() {
|
180
|
-
document.getElementById('message').innerHTML = "main page webSocket connection closed.";
|
181
|
-
};
|
182
|
-
|
183
|
-
|
184
|
-
window.onload = async function() {
|
185
|
-
const payload = {element_ids:['autoTrade', 'optionMovingAverage', 'maxAutoTrades']};
|
186
|
-
await fetchStates(payload);
|
187
|
-
};
|
188
|
-
|
189
|
-
document.getElementById("autoTrade").addEventListener('change', async function() {
|
190
|
-
const states = {
|
191
|
-
autoTrade: document.getElementById('autoTrade').checked.toString(),
|
192
|
-
optionMovingAverage: document.getElementById('optionMovingAverage').value,
|
193
|
-
profitAmount: document.getElementById('profitAmount').value,
|
194
|
-
lossAmount: document.getElementById('lossAmount').value,
|
195
|
-
maxAutoTrades: document.getElementById('maxAutoTrades').value
|
196
|
-
};
|
197
|
-
await saveStates(states);
|
198
|
-
|
199
|
-
const response = await fetch('/autotrade', {
|
200
|
-
method: 'POST',
|
201
|
-
headers: {
|
202
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
203
|
-
},
|
204
|
-
body: JSON.stringify({ 'autoTrade': autoTrade })
|
205
|
-
});
|
206
|
-
});
|
207
|
-
|
208
|
-
|
209
|
-
async function handleChartsButton(symbol) {
|
210
|
-
const response = await fetch('/handle_charts_click', {
|
211
|
-
method: 'POST',
|
212
|
-
headers: {
|
213
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
214
|
-
},
|
215
|
-
body: `symbol=${encodeURIComponent(symbol)}`
|
216
|
-
});
|
217
|
-
const result = await response.json();
|
218
|
-
openURL(result.message);
|
219
|
-
}
|
220
|
-
|
221
|
-
async function handleBitunixButton(symbol) {
|
222
|
-
const response = await fetch('/handle_bitunix_click', {
|
223
|
-
method: 'POST',
|
224
|
-
headers: {
|
225
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
226
|
-
},
|
227
|
-
body: `symbol=${symbol}`
|
228
|
-
});
|
229
|
-
const result = await response.json();
|
230
|
-
openURL(result.message);
|
231
|
-
}
|
232
|
-
|
233
|
-
async function handleAddButton(symbol,close) {
|
234
|
-
let result1 = confirm("Add "+ symbol + " @ " + close.toString());
|
235
|
-
if (result1) {
|
236
|
-
const response = await fetch('/handle_add_click', {
|
237
|
-
method: 'POST',
|
238
|
-
headers: {
|
239
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
240
|
-
},
|
241
|
-
body: `symbol=${encodeURIComponent(symbol)}&close=${encodeURIComponent(close)}`
|
242
|
-
});
|
243
|
-
}
|
244
|
-
}
|
245
|
-
|
246
|
-
async function handleReduceButton(symbol,positionId,qty,close) {
|
247
|
-
let result1 = confirm("Reduce "+ symbol + " @ " + close.toString());
|
248
|
-
if (result1) {
|
249
|
-
const response = await fetch('/handle_reduce_click', {
|
250
|
-
method: 'POST',
|
251
|
-
headers: {
|
252
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
253
|
-
},
|
254
|
-
body: `symbol=${encodeURIComponent(symbol)}&positionId=${encodeURIComponent(positionId)}&qty=${encodeURIComponent(qty)}&close=${encodeURIComponent(close)}`
|
255
|
-
});
|
256
|
-
}
|
257
|
-
}
|
258
|
-
|
259
|
-
async function handleBuyButton(symbol,close) {
|
260
|
-
let result1 = confirm("Buy "+ symbol + " @ " + close.toString());
|
261
|
-
if (result1) {
|
262
|
-
const response = await fetch('/handle_buy_click', {
|
263
|
-
method: 'POST',
|
264
|
-
headers: {
|
265
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
266
|
-
},
|
267
|
-
body: `symbol=${encodeURIComponent(symbol)}&close=${encodeURIComponent(close)}`
|
268
|
-
});
|
269
|
-
}
|
270
|
-
}
|
271
|
-
|
272
|
-
async function handleSellButton(symbol,close) {
|
273
|
-
let result2 = confirm("Sell "+ symbol + " @ " + close.toString());
|
274
|
-
if (result2) {
|
275
|
-
const response = await fetch('/handle_sell_click', {
|
276
|
-
method: 'POST',
|
277
|
-
headers: {
|
278
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
279
|
-
},
|
280
|
-
body: `symbol=${encodeURIComponent(symbol)}&close=${encodeURIComponent(close)}`
|
281
|
-
});
|
282
|
-
}
|
283
|
-
}
|
284
|
-
|
285
|
-
async function handleCloseButton(symbol,positionId,qty,unrealizedPNL,realizedPNL) {
|
286
|
-
let result3 = confirm("Close Position "+ symbol + " with positionid: " + positionId );
|
287
|
-
if (result3) {
|
288
|
-
const response = await fetch('/handle_close_click', {
|
289
|
-
method: 'POST',
|
290
|
-
headers: {
|
291
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
292
|
-
},
|
293
|
-
body: `symbol=${encodeURIComponent(symbol)}&positionId=${encodeURIComponent(positionId)}&qty=${encodeURIComponent(qty)}&unrealizedPNL=${encodeURIComponent(unrealizedPNL)}&realizedPNL=${encodeURIComponent(realizedPNL)}`
|
294
|
-
});
|
295
|
-
}
|
296
|
-
}
|
297
|
-
|
298
|
-
async function handleOrderCloseButton(symbol,orderId) {
|
299
|
-
let result3 = confirm("Close Order "+ symbol + " with orderid: " + orderId );
|
300
|
-
if (result3) {
|
301
|
-
const response = await fetch('/handle_order_close_click', {
|
302
|
-
method: 'POST',
|
303
|
-
headers: {
|
304
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
305
|
-
},
|
306
|
-
body: `symbol=${encodeURIComponent(symbol)}&orderId=${encodeURIComponent(orderId)}`
|
307
|
-
});
|
308
|
-
}
|
309
|
-
}
|
310
|
-
|
311
|
-
|
312
|
-
async function handleRowClick(name) {
|
313
|
-
const response = await fetch('/handle_click', {
|
314
|
-
method: 'POST',
|
315
|
-
headers: {
|
316
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
317
|
-
},
|
318
|
-
body: `name=${name}`
|
319
|
-
});
|
320
|
-
const result = await response.json();
|
321
|
-
openURL(result.message);
|
322
|
-
}
|
323
|
-
|
324
|
-
|
325
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
326
|
-
//display config modal window
|
327
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
328
|
-
//open modal config html
|
329
|
-
document.getElementById("config").addEventListener('click', () => {
|
330
|
-
handleConfigButton();
|
331
|
-
});
|
332
|
-
|
333
|
-
// Open modal and fetch its content
|
334
|
-
async function handleConfigButton() {
|
335
|
-
try{
|
336
|
-
// Fetch modal content
|
337
|
-
const modalContainerWrapper = document.getElementById('modal-container-wrapper'); const modalResponse = await fetch('/config');
|
338
|
-
const modalConfigResponse = await fetch('/config');
|
339
|
-
if (!modalConfigResponse.ok) throw new Error("Failed to fetch config.html");
|
340
|
-
modalContainerWrapper.innerHTML = await modalConfigResponse.text();
|
341
|
-
|
342
|
-
// Fetch environment variables
|
343
|
-
const configResponse = await fetch('/get-config');
|
344
|
-
if (!configResponse.ok) throw new Error("Failed to fetch config variables");
|
345
|
-
const configVars = await configResponse.json();
|
346
|
-
|
347
|
-
// initialize modal
|
348
|
-
configModal = initializeModal('modal-container', 'modal-overlay', 'modal', {
|
349
|
-
top : '10%',
|
350
|
-
left : '10%',
|
351
|
-
width : '80%',
|
352
|
-
height : '80%',
|
353
|
-
maxWidth : '80vw',
|
354
|
-
maxHeight : '100vh',
|
355
|
-
allowMove: false,
|
356
|
-
allowResize: false,
|
357
|
-
onClose: () => {}
|
358
|
-
});
|
359
|
-
|
360
|
-
//open config modal
|
361
|
-
configModal.open()
|
362
|
-
|
363
|
-
// Populate the table
|
364
|
-
const tbody = document.querySelector('#config-table tbody');
|
365
|
-
if (!tbody) throw new Error("<tbody> element not found");
|
366
|
-
tbody.innerHTML = Object.entries(configVars)
|
367
|
-
.map(([key, value]) =>
|
368
|
-
`<tr class="config-item" data-key="${key}" data-value="${value}">
|
369
|
-
<td>${key}</td>
|
370
|
-
<td>${value}</td>
|
371
|
-
</tr>`
|
372
|
-
)
|
373
|
-
.join('');
|
374
|
-
|
375
|
-
// Add click event listener to each environment variable
|
376
|
-
document.querySelectorAll('.config-item').forEach((item) => {
|
377
|
-
item.addEventListener('click', () => {
|
378
|
-
const key = item.getAttribute('data-key');
|
379
|
-
const value = item.getAttribute('data-value');
|
380
|
-
document.getElementById('key').value = key;
|
381
|
-
document.getElementById('value').value = value;
|
382
|
-
});
|
383
|
-
});
|
384
|
-
|
385
|
-
// Handle save form submission
|
386
|
-
const saveForm = document.getElementById('save-config-form');
|
387
|
-
saveForm.addEventListener('submit', async (e) => {
|
388
|
-
e.preventDefault();
|
389
|
-
const formData = new FormData(saveForm);
|
390
|
-
const saveResponse = await fetch('/save-config', {
|
391
|
-
method: 'POST',
|
392
|
-
body: formData,
|
393
|
-
});
|
394
|
-
const saveResult = await saveResponse.json();
|
395
|
-
alert(saveResult.message);
|
396
|
-
|
397
|
-
//update variable on the screen
|
398
|
-
const payload = {element_ids:['autoTrade', 'optionMovingAverage', 'maxAutoTrades']};
|
399
|
-
fetchStates(payload);
|
400
|
-
|
401
|
-
handleConfigButton(); // Reload modal content after saving changes
|
402
|
-
});
|
403
|
-
|
404
|
-
} catch (error) {
|
405
|
-
console.error('Error:', error);
|
406
|
-
}
|
407
|
-
}
|
408
|
-
|
409
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
410
|
-
//display logs modal window
|
411
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
412
|
-
document.getElementById("message").addEventListener('click', () => {
|
413
|
-
handleMessageArea();
|
414
|
-
});
|
415
|
-
|
416
|
-
// Open modal and fetch its content
|
417
|
-
async function handleMessageArea() {
|
418
|
-
try {
|
419
|
-
// Fetch modal content
|
420
|
-
const modalContainerWrapper = document.getElementById('modal-container-wrapper'); const modalResponse = await fetch('/config');
|
421
|
-
const modalLogsResponse = await fetch('/logs');
|
422
|
-
if (!modalLogsResponse.ok) throw new Error("Failed to fetch log.html");
|
423
|
-
modalContainerWrapper.innerHTML = await modalLogsResponse.text();
|
424
|
-
|
425
|
-
// initialize modal
|
426
|
-
configModal = initializeModal('modal-container', 'modal-overlay', 'modal', {
|
427
|
-
top : '10%',
|
428
|
-
left : '10%',
|
429
|
-
width : '80%',
|
430
|
-
height : '80%',
|
431
|
-
maxWidth : '80vw',
|
432
|
-
maxHeight : '80vh',
|
433
|
-
allowMove: false,
|
434
|
-
allowResize: false,
|
435
|
-
onClose: () => {
|
436
|
-
websocket_l.close();
|
437
|
-
}
|
438
|
-
});
|
439
|
-
|
440
|
-
//open config modal
|
441
|
-
configModal.open()
|
442
|
-
|
443
|
-
const logContainer = document.getElementById('log-container');
|
444
|
-
logContainer.innerText = '';
|
445
|
-
|
446
|
-
// Open WebSocket connection
|
447
|
-
const websocket_l = new WebSocket(`ws://${host}:8000/wslogs`);
|
448
|
-
|
449
|
-
websocket_l.onopen = () => {
|
450
|
-
console.log("log WebSocket connection opened.");
|
451
|
-
};
|
452
|
-
|
453
|
-
websocket_l.onmessage = (event) => {
|
454
|
-
logContainer.innerText += event.data + '\n'; // Append new log
|
455
|
-
logContainer.scrollTop = logContainer.scrollHeight; // Auto-scroll
|
456
|
-
};
|
457
|
-
|
458
|
-
websocket_l.onclose = () => {
|
459
|
-
console.log("log WebSocket connection closed.");
|
460
|
-
};
|
461
|
-
|
462
|
-
|
463
|
-
} catch (error) {
|
464
|
-
console.error('Error:', error);
|
465
|
-
}
|
466
|
-
}
|
467
|
-
|
468
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
469
|
-
//display chart modal window
|
470
|
-
///////////////////////////////////////////////////////////////////////////////////////////
|
471
|
-
|
472
|
-
document.addEventListener('DOMContentLoaded', (event) => {
|
473
|
-
attachTableClickHandlerFunction('positions', 0, handleChart);
|
474
|
-
attachTableClickHandlerFunction('orders', 0, handleChart);
|
475
|
-
attachTableClickHandlerFunction('signals', 0, handleChart);
|
476
|
-
attachTableClickHandlerFunction('study', 0, handleChart);
|
477
|
-
attachTableClickHandlerFunction('positionHistory', 0, handleChart);
|
478
|
-
});
|
479
|
-
|
480
|
-
// Open modal and fetch its content
|
481
|
-
async function handleChart(symbol){
|
482
|
-
try {
|
483
|
-
// Fetch modal content
|
484
|
-
const modalContainerWrapper = document.getElementById('modal-container-wrapper'); const modalResponse = await fetch('/config');
|
485
|
-
const modalChartResponse = await fetch(`/chart?symbol=${encodeURIComponent(symbol)}`);
|
486
|
-
if (!modalChartResponse.ok) throw new Error("Failed to fetch chart.html");
|
487
|
-
modalContainerWrapper.innerHTML = await modalChartResponse.text();
|
488
|
-
|
489
|
-
// initialize modal
|
490
|
-
configModal = initializeModal('modal-container', 'modal-overlay', 'modal', {
|
491
|
-
top : '10%',
|
492
|
-
left : '10%',
|
493
|
-
width : '80%',
|
494
|
-
height : '80%',
|
495
|
-
maxWidth : '80vw',
|
496
|
-
maxHeight : '80vw',
|
497
|
-
allowMove: false,
|
498
|
-
allowResize: false,
|
499
|
-
onClose: () => {
|
500
|
-
websocket_c2.close();
|
501
|
-
delete charts['chart'];
|
502
|
-
}
|
503
|
-
});
|
504
|
-
|
505
|
-
//open config modal
|
506
|
-
configModal.open()
|
507
|
-
|
508
|
-
// Open WebSocket connection
|
509
|
-
const websocket_c2 = new WebSocket(`ws://${host}:8000/wschart?ticker=${symbol}`);
|
510
|
-
|
511
|
-
websocket_c2.onopen = () => {
|
512
|
-
console.log("chart WebSocket connection opened.");
|
513
|
-
};
|
514
|
-
|
515
|
-
websocket_c2.onmessage = (event) => {
|
516
|
-
const messageElement = JSON.parse(event.data);
|
517
|
-
document.getElementById('symbol').innerHTML = messageElement.symbol;
|
518
|
-
document.getElementById('close').innerHTML = messageElement.close;
|
519
|
-
|
520
|
-
const data = messageElement.chart;
|
521
|
-
const buysell = messageElement.buysell;
|
522
|
-
const period = messageElement.period;
|
523
|
-
const ema_study = messageElement.ema_study;
|
524
|
-
const ema_chart = messageElement.ema_chart;
|
525
|
-
const macd_study = messageElement.macd_study;
|
526
|
-
const macd_chart = messageElement.macd_chart;
|
527
|
-
const bbm_study = messageElement.bbm_study;
|
528
|
-
const bbm_chart = messageElement.bbm_chart;
|
529
|
-
const rsi_study = messageElement.rsi_study;
|
530
|
-
const rsi_chart = messageElement.rsi_chart;
|
531
|
-
|
532
|
-
if (period === '1m' || period === '5m' || period === '15m') {
|
533
|
-
createOrUpdateChart('chart', data, buysell, ema_study, ema_chart, macd_study, macd_chart, bbm_study, bbm_chart, rsi_study, rsi_chart, 'minute');
|
534
|
-
} else if (period === '1h') {
|
535
|
-
createOrUpdateChart('chart', data, buysell, ema_study, ema_chart, macd_study, macd_chart, bbm_study, bbm_chart, rsi_study, rsi_chart, 'hour');
|
536
|
-
} else if (period === '1d') {
|
537
|
-
createOrUpdateChart('chart', data, buysell, ema_study, ema_chart, macd_study, macd_chart, bbm_study, bbm_chart, rsi_study, rsi_chart, 'day');
|
538
|
-
}
|
539
|
-
};
|
540
|
-
|
541
|
-
websocket_c2.onclose = () => {
|
542
|
-
console.log("chart WebSocket connection closed.");
|
543
|
-
};
|
544
|
-
|
545
|
-
} catch (error) {
|
546
|
-
console.error('Error:', error);
|
547
|
-
}
|
548
|
-
}
|
549
|
-
</script>
|
550
|
-
</body>
|
551
|
-
</html>
|
@@ -1,26 +0,0 @@
|
|
1
|
-
<div id="modal-overlay" class="modal-overlay">
|
2
|
-
<div id="modal-container" class="modal-container">
|
3
|
-
<div id="modal" class="modal">
|
4
|
-
<div class="scrollable-view">
|
5
|
-
<div class="container">
|
6
|
-
<div class="right">
|
7
|
-
<div class="label">Symbol</div>
|
8
|
-
<div id='symbol'></div>
|
9
|
-
</div>
|
10
|
-
<div class="right">
|
11
|
-
<div class="label">Close</div>
|
12
|
-
<div id='close'></div>
|
13
|
-
</div>
|
14
|
-
</div>
|
15
|
-
<div id="chart" class="chart-container">
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
<div class="resize-handle resize-top-right"></div>
|
19
|
-
<div class="resize-handle resize-bottom-right"></div>
|
20
|
-
<div class="resize-handle resize-bottom-left"></div>
|
21
|
-
<div class="resize-handle resize-top-left"></div>
|
22
|
-
<button id="close-modal">Close</button>
|
23
|
-
</div>
|
24
|
-
</div>
|
25
|
-
</div>
|
26
|
-
|
@@ -1,34 +0,0 @@
|
|
1
|
-
<div id="modal-overlay" class="modal-overlay">
|
2
|
-
<div id="modal-container" class="modal-container">
|
3
|
-
<div id="modal" class="modal">
|
4
|
-
<h1>Edit Config</h1>
|
5
|
-
<div class="scrollable-view">
|
6
|
-
<table id="config-table" border="1" width="100%">
|
7
|
-
<thead>
|
8
|
-
<tr>
|
9
|
-
<th>Key</th>
|
10
|
-
<th>Value</th>
|
11
|
-
</tr>
|
12
|
-
</thead>
|
13
|
-
<tbody>
|
14
|
-
<!-- Dynamically populated rows will appear here -->
|
15
|
-
</tbody>
|
16
|
-
</table>
|
17
|
-
</div>
|
18
|
-
|
19
|
-
<div class="resize-handle resize-top-right"></div>
|
20
|
-
<div class="resize-handle resize-bottom-right"></div>
|
21
|
-
<div class="resize-handle resize-bottom-left"></div>
|
22
|
-
<div class="resize-handle resize-top-left"></div>
|
23
|
-
|
24
|
-
<form id="save-config-form">
|
25
|
-
<input type="text" id="key" name="key" placeholder="Key" required>
|
26
|
-
<input type="text" id="value" name="value" placeholder="Value" required>
|
27
|
-
<button type="submit">Save</button>
|
28
|
-
</form>
|
29
|
-
|
30
|
-
<button id="close-modal">Close</button>
|
31
|
-
</div>
|
32
|
-
</div>
|
33
|
-
</div>
|
34
|
-
|
@@ -1,15 +0,0 @@
|
|
1
|
-
<div id="modal-overlay" class="modal-overlay">
|
2
|
-
<div id="modal-container" class="modal-container">
|
3
|
-
<div id="modal" class="modal">
|
4
|
-
<h1>Logs</h1>
|
5
|
-
<div class="scrollable-view">
|
6
|
-
<div id="log-container"></div>
|
7
|
-
</div>
|
8
|
-
<div class="resize-handle resize-top-right"></div>
|
9
|
-
<div class="resize-handle resize-bottom-right"></div>
|
10
|
-
<div class="resize-handle resize-bottom-left"></div>
|
11
|
-
<div class="resize-handle resize-top-left"></div>
|
12
|
-
<button id="close-modal">Close</button>
|
13
|
-
</div>
|
14
|
-
</div>
|
15
|
-
</div>
|