brighter-trading/app.py

248 lines
9.7 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 and interactions.
from data import BrighterData
# Define app
app = Flask(__name__)
sock = Sock(app)
# This object maintains all the application and historical data.
# Access to server, local storage, other classes go through here.
app_data = BrighterData()
# 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 = app_data.get_rendered_data()
js_data = 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 = 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 = app_data.get_signals()
if signals:
resp = {
"reply": "signals",
"data": signals
}
resp = json.dumps(resp)
sock.send(resp)
elif msg_obj['data'] == 'strategies':
strategies = 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':
app_data.delete_signal(msg_obj['data'])
if msg_obj['message_type'] == 'delete_strategy':
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 = 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 = 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('This buy route is currently not being used.')
# app_data.trades.new_trade(
# 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():
print('This sell route is currently not being used.')
# app_data.trades.new_trade(
# 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']
app_data.config.chart_interval = interval_state
elif setting == 'trading_pair':
trading_pair = request.form['trading_pair']
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 app_data.indicators.indicator_list:
if indctr in enabled_indicators:
app_data.indicators.indicator_list[indctr]['visible'] = True
else:
app_data.indicators.indicator_list[indctr]['visible'] = False
# Redirect without reloading history
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>
app_data.indicators.indicator_list[indicator] = attributes
if 'delete' in request.form:
indicator = request.form['delete']
# This will delete in both indicators and config.
app_data.indicators.delete_indicator(indicator)
# Redirect without reloading history
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.
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}')
app_data.config.config_and_states('save')
app_data.candles.set_candle_history()
return redirect('/')
@app.route('/history')
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
def history():
symbol = app_data.config.trading_pair
interval = app_data.config.chart_interval
return jsonify(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(app_data.indicators.indicator_list)
@app.route('/indicator_init')
@cross_origin(origin='localhost', headers=['Content- Type', 'Authorization'])
def indicator_init():
symbol = app_data.config.trading_pair
interval = app_data.config.chart_interval
d = app_data.indicators.get_indicator_data(symbol, interval, 800)
return jsonify(d)