245 lines
9.6 KiB
Python
245 lines
9.6 KiB
Python
import json
|
|
|
|
from flask import Flask, render_template, request, redirect, jsonify
|
|
from flask_cors import cross_origin
|
|
from binance.enums import *
|
|
from flask_sock import Sock
|
|
# Handles all server side data
|
|
import data as bt
|
|
# *NOT DONE YET*
|
|
import trade
|
|
|
|
# Define app
|
|
app = Flask(__name__)
|
|
sock = Sock(app)
|
|
|
|
|
|
# app.config['SECRET_KEY'] = 'The quick brown fox jumps over the lazy dog'
|
|
# app.config['CORS_HEADERS'] = 'Content-Type'
|
|
# cors = CORS(app, resources={r"*": {"origins": "*"}})
|
|
|
|
@app.route('/')
|
|
def index():
|
|
# Passes data into an HTML template and serves it to a locally hosted server
|
|
rendered_data = bt.app_data.get_rendered_data()
|
|
js_data = bt.app_data.get_js_init_data()
|
|
return render_template('index.html',
|
|
title=rendered_data['title'],
|
|
my_balances=rendered_data['my_balances'],
|
|
symbols=rendered_data['symbols'],
|
|
intervals=rendered_data['intervals'],
|
|
interval_state=rendered_data['chart_interval'],
|
|
indicator_types=rendered_data['indicator_types'],
|
|
indicator_list=rendered_data['indicator_list'],
|
|
checked=rendered_data['enabled_indicators'],
|
|
ma_vals=rendered_data['ma_vals'],
|
|
js_data=js_data)
|
|
|
|
|
|
@sock.route('/ws')
|
|
def ws(sock):
|
|
def json_msg_received(msg_obj):
|
|
if 'message_type' in msg_obj:
|
|
if msg_obj['message_type'] == 'candle_data':
|
|
# Send the candle to the BrighterData_obj
|
|
# and forward any returned data to the client.
|
|
r_data = bt.app_data.received_cdata(msg_obj['data'])
|
|
if r_data:
|
|
resp = {
|
|
"reply": "updates",
|
|
"data": r_data
|
|
}
|
|
sock.send(json.dumps(resp))
|
|
|
|
if msg_obj['message_type'] == 'request':
|
|
if msg_obj['data'] == 'signals':
|
|
signals = bt.app_data.get_signals()
|
|
if signals:
|
|
resp = {
|
|
"reply": "signals",
|
|
"data": signals
|
|
}
|
|
resp = json.dumps(resp)
|
|
sock.send(resp)
|
|
elif msg_obj['data'] == 'strategies':
|
|
strategies = bt.app_data.get_strategies()
|
|
if strategies:
|
|
resp = {
|
|
"reply": "strategies",
|
|
"data": strategies
|
|
}
|
|
resp = json.dumps(resp)
|
|
sock.send(resp)
|
|
else:
|
|
print('Warning: Unhandled request!')
|
|
print(msg_obj['data'])
|
|
|
|
if msg_obj['message_type'] == 'delete_signal':
|
|
bt.app_data.delete_signal(msg_obj['data'])
|
|
|
|
if msg_obj['message_type'] == 'delete_strategy':
|
|
bt.app_data.delete_strategy(msg_obj['data'])
|
|
|
|
if msg_obj['message_type'] == 'reply':
|
|
print(msg_obj['rep'])
|
|
print('Reply')
|
|
|
|
if msg_obj['message_type'] == 'new_signal':
|
|
# Send the data to the BrighterData_obj
|
|
# and forward any returned data to the client.
|
|
r_data = bt.app_data.received_new_signal(msg_obj['data'])
|
|
if r_data:
|
|
resp = {
|
|
"reply": "signal_created",
|
|
"data": r_data
|
|
}
|
|
resp = json.dumps(resp)
|
|
sock.send(resp)
|
|
|
|
if msg_obj['message_type'] == 'new_strategy':
|
|
# Send the data to the BrighterData_obj
|
|
# and forward any returned data to the client.
|
|
r_data = bt.app_data.received_new_strategy(msg_obj['data'])
|
|
if r_data:
|
|
resp = {
|
|
"reply": "strategy_created",
|
|
"data": r_data
|
|
}
|
|
resp = json.dumps(resp)
|
|
sock.send(resp)
|
|
return
|
|
|
|
# The rendered page connects to the exchange and relays the candle data back here
|
|
# this socket also handles data and processing requests
|
|
while True:
|
|
msg = sock.receive()
|
|
if msg:
|
|
# If in json format the message gets converted into a dictionary
|
|
# otherwise it is handled as a status signal from the client
|
|
try:
|
|
msg_obj = json.loads(msg)
|
|
json_msg_received(msg_obj)
|
|
except json.JSONDecodeError:
|
|
print(f'Msg received from client: {msg}')
|
|
|
|
|
|
@app.route('/buy', methods=['POST'])
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def buy():
|
|
print(request.form) # Debug ******
|
|
trade.order(
|
|
symbol=request.form['symbol'], side=SIDE_BUY,
|
|
type=ORDER_TYPE_MARKET, quantity=request.form['quantity'])
|
|
return redirect('/')
|
|
|
|
|
|
@app.route('/sell', methods=['POST'])
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def sell():
|
|
trade.order(
|
|
symbol=request.form['symbol'], side=SIDE_SELL,
|
|
type=ORDER_TYPE_MARKET, quantity=request.form['quantity'])
|
|
return redirect('/')
|
|
|
|
|
|
@app.route('/settings', methods=['POST'])
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def settings():
|
|
setting = request.form['setting']
|
|
if setting == 'interval':
|
|
interval_state = request.form['timeframe']
|
|
bt.app_data.config.chart_interval = interval_state
|
|
elif setting == 'trading_pair':
|
|
trading_pair = request.form['trading_pair']
|
|
bt.app_data.config.trading_pair = trading_pair
|
|
elif setting == 'toggle_indicator':
|
|
# Get a list of indicators to enable
|
|
enabled_indicators = []
|
|
for i in request.form:
|
|
if request.form[i] == 'indicator':
|
|
enabled_indicators.append(i)
|
|
# Set visibility for all indicators according to <enabled_indicators>
|
|
for indctr in bt.app_data.indicators.indicator_list:
|
|
if indctr in enabled_indicators:
|
|
bt.app_data.indicators.indicator_list[indctr]['visible'] = True
|
|
else:
|
|
bt.app_data.indicators.indicator_list[indctr]['visible'] = False
|
|
# Redirect without reloading history
|
|
bt.app_data.config.config_and_states('save')
|
|
return redirect('/')
|
|
|
|
elif setting == 'edit_indicator':
|
|
if 'submit' in request.form:
|
|
# Get the name of the indicator
|
|
indicator = request.form['submit']
|
|
# Drop the name and action from our received data
|
|
attributes = dict(list(request.form.items())[2:])
|
|
# All the numbers are string now so turn them back to (int)
|
|
for a in attributes:
|
|
if attributes[a].isdigit():
|
|
attributes[a] = int(attributes[a])
|
|
# if visible is unchecked it doesn't get sent by the form
|
|
if 'visible' not in attributes:
|
|
attributes.update({'visible': False})
|
|
# Set the data in indicators according to <attributes>
|
|
bt.app_data.indicators.indicator_list[indicator] = attributes
|
|
|
|
if 'delete' in request.form:
|
|
indicator = request.form['delete']
|
|
# This will delete in both indicators and config.
|
|
bt.app_data.indicators.delete_indicator(indicator)
|
|
# Redirect without reloading history
|
|
bt.app_data.config.config_and_states('save')
|
|
return redirect('/')
|
|
|
|
elif setting == 'new_indicator':
|
|
if 'newi_name' in request.form:
|
|
indcr = request.form['newi_name']
|
|
indtyp = request.form['newi_type']
|
|
properties = {}
|
|
if request.form['new_prop_obj']:
|
|
list_of_dic = json.loads(request.form['new_prop_obj'])
|
|
# All the numbers are string now so turn them back to (int)
|
|
properties = {}
|
|
for prop in list_of_dic:
|
|
# Get the key for this object
|
|
key = next(iter(prop))
|
|
# access the value of this object
|
|
value = prop[key]
|
|
if value.isdigit():
|
|
value = int(value)
|
|
properties[key] = value
|
|
# Should create in indicators and update the list in config.
|
|
bt.app_data.indicators.create_indicator(name=indcr, itype=indtyp, properties=properties)
|
|
|
|
|
|
else:
|
|
print('ERROR SETTING VALUE')
|
|
print(f'The string received by the server was: /n{request.form}')
|
|
bt.app_data.config.config_and_states('save')
|
|
bt.app_data.candles.set_candle_history()
|
|
return redirect('/')
|
|
|
|
|
|
@app.route('/history')
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def history():
|
|
symbol = bt.app_data.config.trading_pair
|
|
interval = bt.app_data.config.chart_interval
|
|
return jsonify(bt.app_data.candles.get_candle_history(symbol, interval, 1000))
|
|
|
|
|
|
@app.route('/saved_data')
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def saved_data():
|
|
return jsonify(bt.app_data.indicators.indicator_list)
|
|
|
|
|
|
@app.route('/indicator_init')
|
|
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
|
|
def indicator_init():
|
|
symbol = bt.app_data.config.trading_pair
|
|
interval = bt.app_data.config.chart_interval
|
|
d = bt.app_data.indicators.get_indicator_data(symbol, interval, 800)
|
|
return jsonify(d)
|