Арбитраж криптовалютных бирж на Python


В этой статье мы рассмотрим вариант создания пет-проекта для арбитража криптовалютных бирж. Для этой задачи мы возьмем за основу предыдущий наш проект Web приложение на Python Flask/PySide6 в виде десктопной программы. У нас также уже есть заготовки для получения данных с криптовалютных бирж. Осталось это все объединить в один проект.
В этой статье мы рассмотрим вариант создания пет-проекта для арбитража криптовалютных бирж. Для этой задачи мы возьмем за основу предыдущий наш проект Web приложение на Python Flask/PySide6 в виде десктопной программы. У нас также уже есть заготовки для получения данных с криптовалютных бирж. Осталось это все объединить в один проект.
Как это работает
- start: Основной скрипт, который запускает веб-службу, браузер, сокет сервер в подпроцессы. Так же запускается моудль exchanges для сбора данных с криптовалютных бирж;
- web_service: Веб-служба, работающая на Flask, обрабатывает запросы и предоставляет интерфейс;
- browser: Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения сайта;
- socket_server: Запускает websockets для быстрой передачи данных;
- socket_client: Подключается к socket_server для передачи данных от модуля exchanges к web_service;
- exchanges: Директория, в которой находится WebSocket для криптовалютных бирж (Binance, Bitget, Bybit, Coinbase, Gate, Kraken, Okx).
- design: Директория, в которой находится структура сайта (HTML, CSS, JS);
start
Основная задача этого файла заключается в том, что бы запустить подпроцессы, передать в них аргументы и завершить эти процессы по окончанию работы основного процесса.
#-*- coding: UTF-8 -*-
import time, subprocess
from modules.exchanges import Trading_platforms
class Main():
def __init__(self):
host = '127.0.0.1'
port = '5000'
try:
socket_server = subprocess.Popen(["python", "modules/socket_server.py"])
web_service = subprocess.Popen(["python", "modules/web_service.py", host, port])
browser = subprocess.Popen(["python", "modules/browser.py", host, port])
# Данные с торговых площадок
Trading_platforms()
while True:
time.sleep(10)
except KeyboardInterrupt:
pass
print("Основной процесс завершен. Завершаем субпроцесс.")
socket_server.terminate()
web_service.terminate()
browser.terminate()
socket_server.wait()
web_service.wait()
browser.wait()
print("Субпроцессы завершены.")
if __name__ == "__main__":
Main()
web_service
Пример примитивного web-ядра. Для наших задач на данный момент более чем подходит. Это web-ядро может обробатьвать GET запросы с параметрами. Проводить очистку передаваемых параметров и структурировать их в словарь. Обработку POST запросов реализуем позднее.
#-*- coding: UTF-8 -*-
from flask import Flask, request, Response
import re, mimetypes, sys
host = sys.argv[1]
port = sys.argv[2]
mimetypes.add_type('font/woff', '.woff')
mimetypes.add_type('font/woff2', '.woff2')
mimetypes.add_type('font/woff', '.woff')
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
mimetypes.add_type('font/ttf', '.ttf')
class webService:
def __init__(self):
self.app = Flask(__name__)
# Получение запроса
@self.app.route('/', defaults={'path': ''})
@self.app.route('/', methods=['GET', 'POST'])
def route(path):
answer = self.process_route()
return Response(response = answer['response'], status = answer['status'], mimetype = answer['mimetype'])
self.app.run(host=host, port=port, debug=True)
# Определение mimeType
def get_mime_type(self, file_path):
mime_type, _ = mimetypes.guess_type(file_path)
return mime_type
# Изменение данных в строке с помощью replace через цикл
def replace_str(self, strData, mData):
for keyItem, dataItem in mData.items():
strData = strData.replace(keyItem, dataItem)
return strData
# Очистка параметров
def clean_string(self, input_string):
cleaned_string = re.sub(r'[^a-zA-Z0-9]', '', input_string)
return cleaned_string
# Обработка входящих параметров
def proccess_params(self):
result = {}
try:
urlRequest = request.url
mParam = urlRequest.split('?')
if len(mParam) > 1:
mVar = mParam[1].split('&')
for item in mVar:
mItem = item.split('=')
if mItem[0] == '' or len(mItem) == 1:
continue
result[self.clean_string(mItem[0])] = self.clean_string(mItem[1])
except Exception as e:
print('proccess_params: '+str(e))
return result
# Работа с шаблоном
def process_template(self, path_file, typeRead = 'r'):
try:
if typeRead == 'rb':
with open(path_file, typeRead) as f:
result = f.read()
else:
with open(path_file, typeRead, encoding='utf-8') as f:
result = f.read()
except Exception as e:
print(e)
raise Exception('404')
return result
# Обработка запроса
def process_route(self):
result = {'status': 200, 'response': '', 'mimetype': 'text/html', 'typeRead': 'r'}
try:
server_host = str(request.scheme)+'://'+str(request.server[0])+':'+str(request.server[1])
request_data = {'method': request.method, 'path': request.view_args['path'].split('/'), 'variable': self.proccess_params()}
if request_data['method'] == 'GET':
if request_data['path'][0] == '':
request_data['path'][0] = 'index.html'
# Подгрузка страницы
if len(request_data['path']) == 1:
result['response'] = self.process_template('design/template/'+request_data['path'][0])
# Подгрузка дизайна
elif request_data['path'][0] == 'design':
result['mimetype'] = self.get_mime_type(request.view_args['path'])
mMimetype = str(result['mimetype']).split('/')
result['typeRead'] = 'rb' if mMimetype[0] == 'image' or mMimetype[0] == 'font' or mMimetype[0] == 'application' else 'r'
result['response'] = self.process_template(request.view_args['path'], result['typeRead'])
if result['response'] == False:
raise Exception('404')
else:
raise Exception('404')
else:
raise Exception('404')
except Exception as e:
# Подгрузка 404 страницы
result['response'] = self.process_template('design/template/404.html')
result['status'] = 404
if result['typeRead'] != 'rb':
mData = {'SERVER_HOST': server_host}
result['response'] = self.replace_str(result['response'], mData)
return result
if __name__ == "__main__":
webService()
browser
Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения полученной информации от web_service.
#-*- coding: UTF-8 -*-
import sys
from PySide6.QtCore import QUrl
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtWebEngineWidgets import QWebEngineView
host = sys.argv[1]
port = sys.argv[2]
url = 'http://'+host+':'+port
class Browser():
def __init__(self):
app = QApplication(sys.argv)
mw = QMainWindow()
mw.setWindowTitle("Exchange arbitration")
mw.setGeometry(100, 100, 1300, 700)
mw.browser = QWebEngineView()
mw.browser.setUrl(QUrl(url))
mw.setCentralWidget(mw.browser)
mw.show()
sys.exit(app.exec())
if __name__ == "__main__":
Browser()
socket_server
Пример простого сервера веб-сокетов. К нему подключен модуль exchanges через модуль socket_client, который будет передавать данные с торговых бирж на внешнюю сторону веб-сервиса.
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import asyncio
import websockets
client_list = []
async def handler(websocket, port):
client_list.append(websocket)
while True:
try:
message = await websocket.recv()
await broadcast(message, websocket)
except Exception as e:
client_list.remove(websocket)
break
async def broadcast(message, websocket):
for client in client_list:
if client != websocket:
await client.send(message)
async def main():
async with websockets.serve(handler, "", 9501):
await asyncio.Future()
if __name__ == "__main__":
asyncio.run(main())
socket_client
Пример web-сокет клиента для подключения к web-сокет серверу. Данные отправляются через модуль exchanges.
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import time, threading, websocket, json
class Socket_client():
def __init__(self):
self.statusConnect = False
ws = threading.Thread(target=self.start, daemon=True)
ws.start()
def sendData(self, mData):
try:
if self.statusConnect == True:
self.wsa.send(json.dumps(mData))
except Exception as e:
print(e)
def on_open(self, ws):
self.statusConnect = True
def start(self):
while True:
try:
self.wsa = websocket.WebSocketApp('ws://127.0.0.1:9501', on_open = self.on_open)
self.wsa.run_forever()
raise Exception('Socket_clietn - Off')
except Exception as e:
print(e)
self.statusConnect = False
time.sleep(5)
Запуск
Установите необходимые библиотеки:
pip install flask PySide6
Запустите start.py
python start.py
После запуска приложение откроется в виде окна, а внутри него будет отображаться веб-интерфейс, работающий на Flask.
Исходный код- 07.01.2025
- 63
- 1
Арбитраж криптовалютных бирж на Python
В этой статье мы рассмотрим вариант создания пет-проекта для арбитража криптовалютных бирж. Для этой задачи мы возьмем за основу предыдущий наш проект Web приложение на Python Flask/PySide6 в виде десктопной программы. У нас также уже есть заготовки для получения данных с криптовалютных бирж. Осталось это все объединить в один проект.
Как это работает
- start: Основной скрипт, который запускает веб-службу, браузер, сокет сервер в подпроцессы. Так же запускается моудль exchanges для сбора данных с криптовалютных бирж;
- web_service: Веб-служба, работающая на Flask, обрабатывает запросы и предоставляет интерфейс;
- browser: Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения сайта;
- socket_server: Запускает websockets для быстрой передачи данных;
- socket_client: Подключается к socket_server для передачи данных от модуля exchanges к web_service;
- exchanges: Директория, в которой находится WebSocket для криптовалютных бирж (Binance, Bitget, Bybit, Coinbase, Gate, Kraken, Okx).
- design: Директория, в которой находится структура сайта (HTML, CSS, JS);
start
Основная задача этого файла заключается в том, что бы запустить подпроцессы, передать в них аргументы и завершить эти процессы по окончанию работы основного процесса.
#-*- coding: UTF-8 -*-
import time, subprocess
from modules.exchanges import Trading_platforms
class Main():
def __init__(self):
host = '127.0.0.1'
port = '5000'
try:
socket_server = subprocess.Popen(["python", "modules/socket_server.py"])
web_service = subprocess.Popen(["python", "modules/web_service.py", host, port])
browser = subprocess.Popen(["python", "modules/browser.py", host, port])
# Данные с торговых площадок
Trading_platforms()
while True:
time.sleep(10)
except KeyboardInterrupt:
pass
print("Основной процесс завершен. Завершаем субпроцесс.")
socket_server.terminate()
web_service.terminate()
browser.terminate()
socket_server.wait()
web_service.wait()
browser.wait()
print("Субпроцессы завершены.")
if __name__ == "__main__":
Main()
web_service
Пример примитивного web-ядра. Для наших задач на данный момент более чем подходит. Это web-ядро может обробатьвать GET запросы с параметрами. Проводить очистку передаваемых параметров и структурировать их в словарь. Обработку POST запросов реализуем позднее.
#-*- coding: UTF-8 -*-
from flask import Flask, request, Response
import re, mimetypes, sys
host = sys.argv[1]
port = sys.argv[2]
mimetypes.add_type('font/woff', '.woff')
mimetypes.add_type('font/woff2', '.woff2')
mimetypes.add_type('font/woff', '.woff')
mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
mimetypes.add_type('font/ttf', '.ttf')
class webService:
def __init__(self):
self.app = Flask(__name__)
# Получение запроса
@self.app.route('/', defaults={'path': ''})
@self.app.route('/', methods=['GET', 'POST'])
def route(path):
answer = self.process_route()
return Response(response = answer['response'], status = answer['status'], mimetype = answer['mimetype'])
self.app.run(host=host, port=port, debug=True)
# Определение mimeType
def get_mime_type(self, file_path):
mime_type, _ = mimetypes.guess_type(file_path)
return mime_type
# Изменение данных в строке с помощью replace через цикл
def replace_str(self, strData, mData):
for keyItem, dataItem in mData.items():
strData = strData.replace(keyItem, dataItem)
return strData
# Очистка параметров
def clean_string(self, input_string):
cleaned_string = re.sub(r'[^a-zA-Z0-9]', '', input_string)
return cleaned_string
# Обработка входящих параметров
def proccess_params(self):
result = {}
try:
urlRequest = request.url
mParam = urlRequest.split('?')
if len(mParam) > 1:
mVar = mParam[1].split('&')
for item in mVar:
mItem = item.split('=')
if mItem[0] == '' or len(mItem) == 1:
continue
result[self.clean_string(mItem[0])] = self.clean_string(mItem[1])
except Exception as e:
print('proccess_params: '+str(e))
return result
# Работа с шаблоном
def process_template(self, path_file, typeRead = 'r'):
try:
if typeRead == 'rb':
with open(path_file, typeRead) as f:
result = f.read()
else:
with open(path_file, typeRead, encoding='utf-8') as f:
result = f.read()
except Exception as e:
print(e)
raise Exception('404')
return result
# Обработка запроса
def process_route(self):
result = {'status': 200, 'response': '', 'mimetype': 'text/html', 'typeRead': 'r'}
try:
server_host = str(request.scheme)+'://'+str(request.server[0])+':'+str(request.server[1])
request_data = {'method': request.method, 'path': request.view_args['path'].split('/'), 'variable': self.proccess_params()}
if request_data['method'] == 'GET':
if request_data['path'][0] == '':
request_data['path'][0] = 'index.html'
# Подгрузка страницы
if len(request_data['path']) == 1:
result['response'] = self.process_template('design/template/'+request_data['path'][0])
# Подгрузка дизайна
elif request_data['path'][0] == 'design':
result['mimetype'] = self.get_mime_type(request.view_args['path'])
mMimetype = str(result['mimetype']).split('/')
result['typeRead'] = 'rb' if mMimetype[0] == 'image' or mMimetype[0] == 'font' or mMimetype[0] == 'application' else 'r'
result['response'] = self.process_template(request.view_args['path'], result['typeRead'])
if result['response'] == False:
raise Exception('404')
else:
raise Exception('404')
else:
raise Exception('404')
except Exception as e:
# Подгрузка 404 страницы
result['response'] = self.process_template('design/template/404.html')
result['status'] = 404
if result['typeRead'] != 'rb':
mData = {'SERVER_HOST': server_host}
result['response'] = self.replace_str(result['response'], mData)
return result
if __name__ == "__main__":
webService()
browser
Интерфейсный модуль на PySide6, который использует встроенный браузер (QWebEngineView) для отображения полученной информации от web_service.
#-*- coding: UTF-8 -*-
import sys
from PySide6.QtCore import QUrl
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtWebEngineWidgets import QWebEngineView
host = sys.argv[1]
port = sys.argv[2]
url = 'http://'+host+':'+port
class Browser():
def __init__(self):
app = QApplication(sys.argv)
mw = QMainWindow()
mw.setWindowTitle("Exchange arbitration")
mw.setGeometry(100, 100, 1300, 700)
mw.browser = QWebEngineView()
mw.browser.setUrl(QUrl(url))
mw.setCentralWidget(mw.browser)
mw.show()
sys.exit(app.exec())
if __name__ == "__main__":
Browser()
socket_server
Пример простого сервера веб-сокетов. К нему подключен модуль exchanges через модуль socket_client, который будет передавать данные с торговых бирж на внешнюю сторону веб-сервиса.
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import asyncio
import websockets
client_list = []
async def handler(websocket, port):
client_list.append(websocket)
while True:
try:
message = await websocket.recv()
await broadcast(message, websocket)
except Exception as e:
client_list.remove(websocket)
break
async def broadcast(message, websocket):
for client in client_list:
if client != websocket:
await client.send(message)
async def main():
async with websockets.serve(handler, "", 9501):
await asyncio.Future()
if __name__ == "__main__":
asyncio.run(main())
socket_client
Пример web-сокет клиента для подключения к web-сокет серверу. Данные отправляются через модуль exchanges.
#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import time, threading, websocket, json
class Socket_client():
def __init__(self):
self.statusConnect = False
ws = threading.Thread(target=self.start, daemon=True)
ws.start()
def sendData(self, mData):
try:
if self.statusConnect == True:
self.wsa.send(json.dumps(mData))
except Exception as e:
print(e)
def on_open(self, ws):
self.statusConnect = True
def start(self):
while True:
try:
self.wsa = websocket.WebSocketApp('ws://127.0.0.1:9501', on_open = self.on_open)
self.wsa.run_forever()
raise Exception('Socket_clietn - Off')
except Exception as e:
print(e)
self.statusConnect = False
time.sleep(5)
Запуск
Установите необходимые библиотеки:
pip install flask PySide6
Запустите start.py
python start.py
После запуска приложение откроется в виде окна, а внутри него будет отображаться веб-интерфейс, работающий на Flask.
Исходный код