From 003d8458d144b355d85ec48ef7344a776f3135a2 Mon Sep 17 00:00:00 2001 From: "lucas.toniutti" <lucas.toniutti@etu.hesge.ch> Date: Mon, 12 Jun 2023 15:28:55 +0200 Subject: [PATCH] =?UTF-8?q?Am=C3=A9lioration=20du=20graphique?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main/Decision.py | 2 - main/__pycache__/Decision.cpython-310.pyc | Bin 6570 -> 6583 bytes main/__pycache__/simulation.cpython-310.pyc | Bin 12511 -> 13384 bytes main/backend.py | 153 ++++- main/simulation.py | 61 +- main/templates/.DS_Store | Bin 6148 -> 6148 bytes main/templates/index.html | 13 +- main/templates/indexD3Chart.html | 626 ++++++++++++++++++++ 8 files changed, 828 insertions(+), 27 deletions(-) create mode 100644 main/templates/indexD3Chart.html diff --git a/main/Decision.py b/main/Decision.py index d72f7a2..7ebc93d 100644 --- a/main/Decision.py +++ b/main/Decision.py @@ -95,7 +95,6 @@ class Decision: #Launch SMA calculation # Mettre les décisions - self.calculateSMA(date,symbol,price,mas) if self.indexTickerSim >= len(sim.histo_prices)-1: break @@ -140,7 +139,6 @@ class Decision: #If simulated ==> launch a bunch of tests print("SIMULATED") self.sim = Simulation(None,None,markets[0],bases[0],targets[0]) - #For each market apply lagrange to get the price of ohlc datas for i,market in enumerate(markets): self.sim.startsimulation("lagrange",market,show_graph,dateStart,dateEnd) diff --git a/main/__pycache__/Decision.cpython-310.pyc b/main/__pycache__/Decision.cpython-310.pyc index 7c3a489da670638c0d0e0964fa147338a8ae993d..1d77cd921b83a35d7cc3672a2ca5f7f4f160f4ef 100644 GIT binary patch delta 139 zcmZ2wyxo{LpO=@5fq{X+{zGGm+(uqz7Dl(pf-G|4#hJOKIf*5yr9~x0i7A<R>B&Wv z1ts~LEm`zg7+E%Fa_BQMW^JCy`Iniobn<jwT}GzKM|ss5pKpH4Yt6{Ge6lA02F3%M uZ}FdIWIVEYncyQP#+#cvMf#Z-nI=n$KVsFE;N~!zBr%mSYV$M+5k>&dR4gq3 delta 127 zcmdmPyvmq2pO=@5fq{XcGPo>7XCp5&3!~*^K^8f##Dap7qQsQUy!6d(Ecz^rteeX? z^cfkmH!tJ-%gk6dc?qvBBlF}-yy}e4Hvi(aW@KDB*^GY!<Dt#Z`A;)49^1TG@DUT^ i?ak9f`k5G6CaZ}*V%3r0<}jYjD>0Sv*5<_$B8&h+TPHyP diff --git a/main/__pycache__/simulation.cpython-310.pyc b/main/__pycache__/simulation.cpython-310.pyc index 837832285c085945277a863706f91789fac2e686..e6f8c914f44e21d1aee9d3a287b06ef1cb1f8865 100644 GIT binary patch delta 4849 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 delta 4102 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 P3V_29K^RZ|W*h_n&(f1O diff --git a/main/backend.py b/main/backend.py index 54f8fb2..724be19 100644 --- a/main/backend.py +++ b/main/backend.py @@ -67,7 +67,6 @@ def index(): global stickyForm global resetParams - url = None figJson = None results = None if resetParams == 1: @@ -75,11 +74,13 @@ def index(): if dec.export_result != []: simulationInProgress = False - figJson = createFig(dec.sim.histo_prices, dec.sim.active_orders, dec.sma[market], dec.mas[0], market) - # url = 'static/imgSimulation/simulation.png' + # figJson = createFig(dec.sim.histo_prices, dec.sim.active_orders, dec.sma[market], dec.mas[0], market) + tmpOrder = [dec.sim.winsAV, dec.sim.lossAV, dec.sim.winsVA, dec.sim.lossVA] + # print(tmpOrder) + figJson = createFigPyplot(market,dec.sma[market], dec.mas[0], tmpOrder) results = getResults() - reponse = make_response(render_template('index.html', async_mode=socket_.async_mode, simulation=url, inProgress=simulationInProgress, fig=figJson, res=results, err=dictError, stickyForm=stickyForm)) - reponse.headers['Content-Security-Policy'] = "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.5.1/plotly.min.js https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js https://fonts.googleapis.com/ https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" + reponse = make_response(render_template('index.html', async_mode=socket_.async_mode, inProgress=simulationInProgress, fig=figJson, res=results, err=dictError, stickyForm=stickyForm)) + # reponse.headers['Content-Security-Policy'] = "style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.5.1/plotly.min.js https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js https://fonts.googleapis.com/ https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" if resetParams == 2: resetParams = 1 dictError = {} @@ -208,15 +209,150 @@ def checkGeneralInput(takeprofit, stoploss, candleSize, dateSimStart, dateSimEnd dictError['ma'] = 'is-valid' return dictError +def createFigPyplot(market, mas, arraySma, orders): + dataChart = dec.sim.candle_prices + + months = {"January": "Janvier", "February": "Février", "March": "Mars", "April": "Avril", "May": "Mai", "June": "Juin", "July": "Juillet", "August": "Août", "September": "Septembre", "October": "Octobre", "November": "Novembre", "December": "Décembre"} + + textHover = [] + for item in dataChart: + date = datetime.datetime.strptime(item["date"], '%Y-%m-%d %H:%M:%S') + formatted_date = date.strftime('%d %B \'%y\n%H:%M') + month = date.strftime('%B') + if month in months: + formatted_date = formatted_date.replace(month, months[month]) + formatted_date = '<br>'.join(formatted_date.split('\n')) + if item["close"] > item["open"]: + color = 'green' + else: + color = 'red' + + text = f"<span style='color: white;'>O</span> <span style='color: {color}'>{str(item['open'])}</span><br><span style='color: white;'>H</span> <span style='color: {color}'>{str(item['high'])}</span><br><span style='color: white;'>L</span> <span style='color: {color}'>{str(item['low'])}</span><br><span style='color: white;'>C</span> <span style='color: {color}'>{str(item['close'])}</span><br><span style='color: dimgrey'>{formatted_date}</span>" + textHover.append(text) + fig = go.Figure(data=[ + go.Candlestick( + x=[item["date"] for item in dataChart], + open=[item['open'] for item in dataChart], + high=[item['high'] for item in dataChart], + low=[item['low'] for item in dataChart], + close=[item['close'] for item in dataChart], + text=textHover, + hoverinfo="text", + name="Prix" + + )]) + + smaData = {sma: {'price': [], 'date': []} for sma in arraySma} + for sma, values in mas.items(): + for value in values: + smaData[int(sma)]['price'].append(value[0]) + smaData[int(sma)]['date'].append(value[1]) + + for i, sma in enumerate(arraySma): + fig.add_trace( + go.Scatter( + x=smaData[sma]['date'], + y=smaData[sma]['price'], + mode='lines', + name=f'SMA{sma}', + hoverinfo="none", + line=dict(color=['rgba(0, 0, 255, 0.3)', 'rgba(128, 0, 128, 0.3)'][i]) + ) + ) + + avWins, avLoss, vaWins, vaLoss = orders + print(avWins) + + for data, color, symbol, name, endName in [ + (avWins, 'green', 'triangle-up', 'AV Gains', 'Fin AV Gains'), + (avLoss, 'red', 'triangle-up', 'AV Pertes', 'Fin AV Pertes'), + (vaWins, 'green', 'triangle-down', 'VA Gains', 'Fin VA Gains'), + (vaLoss, 'red', 'triangle-down', 'VA Pertes', 'Fin VA Pertes') + ]: + fig.add_trace( + go.Scatter( + x=[order[0]['date'] for order in data], + y=[order[0]['price'] for order in data], + mode='markers', + name=name, + hoverinfo="name", + marker=dict( + symbol=symbol, + size=17, + color=color + ), + legendgroup=name + ) + ) + fig.add_trace( + go.Scatter( + showlegend=False, + x=[order[0]['timeExit'] for order in data], + y=[order[1] for order in data], + mode='markers', + name=endName, + hoverinfo="name", + marker=dict( + symbol='circle', + size=6, + color='black' + ), + legendgroup=name + ) + ) + + for data in [avWins, avLoss, vaWins, vaLoss]: + for order in data: + fig.add_trace( + go.Scatter( + x=[order[0]['date'], order[0]['timeExit']], + y=[order[0]['price'], order[1]], + mode='lines', + line=dict(color='black'), + hoverinfo="none", + showlegend=False, + legendgroup='AV Gains' if order in avWins else 'AV Pertes' if order in avLoss else 'VA Gains' if order in vaWins else 'VA Pertes' + ) + ) + fig.update_layout( + xaxis_rangeslider_visible=False, + title="Simulation sur le marché " + market, + xaxis_title="Date", + yaxis_title="Prix", + hovermode="closest", + hoverlabel=dict( + bgcolor="rgba(123, 132, 144, 0.4)", + font_size=16, + align="auto", + ) + ) + fig.update_layout(plot_bgcolor='#f2f2f2') + fig.update_yaxes(fixedrange=False) + fig.update_layout() + figJson = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder) + return figJson + + def createFig(prices,orders,mas,periodes,market): prices = dec.sim.histo_prices prices=pd.DataFrame(prices,columns=['price','date']) + print(prices) + print("//////////////////////////////// -> orders") + print(orders) + print("//////////////////////////////// -> mas") + print(mas) + print("//////////////////////////////// -> periodes") + print(periodes) + print("//////////////////////////////// -> market") + + print(market) + figJson= dec.sim.candle_prices + fig = go.Figure() layout = go.Layout( plot_bgcolor='#efefef', - # Font Families font_family='Monospace', font_color='#000000', font_size=20, @@ -232,7 +368,6 @@ def createFig(prices,orders,mas,periodes,market): df_order_av = df_order[df_order['type'] == 'AV'] df_order_va = df_order[df_order['type'] == 'VA'] - # put in rgbSMA array the rgb values for green and in other index the rgb values for light green rgbSMA = [[0,255,0], [0,200,0]] cpt = 0 for p in periodes: @@ -244,7 +379,6 @@ def createFig(prices,orders,mas,periodes,market): go.Scatter( x=df['date'], y=df['sma'], - #generate random color line=dict(color=f'rgb({rgbSMA[cpt][0]},{rgbSMA[cpt][1]},{rgbSMA[cpt][2]})', width=2), name='sma'+str(p) ) @@ -305,9 +439,6 @@ def getResults(): for j in dict['losses']: if i == j: dict['moneyLosses'][i] = dict['startBalance'][i] * (round(dict['losses'][j],2) * 0.01) - - print(dict['moneyProfits']) - print(dict['moneyLosses']) return dict diff --git a/main/simulation.py b/main/simulation.py index 25580c6..4100240 100644 --- a/main/simulation.py +++ b/main/simulation.py @@ -43,6 +43,7 @@ from others.plotting_lib import plotCandles class Simulation: def __init__(self,sl,tp, market,base, target): self.strategie = "Doc simulus" + self.candle_prices = [] self.histo_prices= [] self.histo_candles= [] self.symbols = [] @@ -127,23 +128,28 @@ class Simulation: self.target = target self.market = market self.start_time =dt.now() + self.candle_prices = [] #Get ochl candle and polynomial transform to get a price ticker and a given time periode def calcOCLH(self,slices_sec,periode_base,format,symbol,show_graph,dateStart,dateEnd): random.seed(dt.now()) res=[] + resCandle = [] echant_x =[] - + cpt = 0 + tmpCandle = {} for i in range(1,int(periode_base/slices_sec)): echant_x.append(i*slices_sec) if format == True: candles = format_prices("simul") else: self.histo_candles = getHistoCandles(symbol,dateStart, dateEnd) + # print(self.histo_candles) candles = self.histo_candles pourcentage = settings.progressBar for c in candles: + Candles = {} xs=[] ys=[] # print(c) @@ -151,7 +157,9 @@ class Simulation: currentDate = dt.strptime(date,"%Y-%m-%d %H:%M:%S.%fZ") - + + + if format== False: date =self.formatDate(date) c = json.loads(c[0]) @@ -163,7 +171,6 @@ class Simulation: c = json.loads(c[0]) start = c["Open"] - tmpDateStart = dt.strptime(dateStart,"%Y-%m-%d %H:%M:%S.%fZ") tmpDateEnd = dt.strptime(dateEnd,"%Y-%m-%d %H:%M:%S.%fZ") totalDuration = (tmpDateEnd - tmpDateStart).total_seconds() @@ -172,10 +179,37 @@ class Simulation: settings.progressBar = pourcentage + (elapsedDuration / totalDuration) * (95-pourcentage) # print(percentage) #print(f"DATE Candle : {dt.fromtimestamp(date)}") - date = dt.fromtimestamp(date) - datetime.timedelta(0,periode_base) - #print(f"DATE calc : {date}") - + + if cpt == 0: + tmpCandle["open"] = c["Open"] + tmpCandle["date"] = str(date) + tmpCandle["high"] =c["High"] + tmpCandle["low"] =c["Low"] + elif cpt == 1: + if c["High"] > tmpCandle["high"]: + tmpCandle["high"] =c["High"] + if c["Low"] < tmpCandle["low"]: + tmpCandle["low"] =c["Low"] + elif cpt == 2: + if c["High"] > tmpCandle["high"]: + tmpCandle["high"] =c["High"] + if c["Low"] < tmpCandle["low"]: + tmpCandle["low"] =c["Low"] + tmpCandle["close"] =c["Close"] + Candles = tmpCandle + resCandle.append(Candles) + tmpCandle = {} + cpt = -1 + cpt += 1 + + # Candles["open"] = c["Open"] + # Candles["high"] = c["High"] + # Candles["low"] = c["Low"] + # Candles["close"] = c["Close"] + # Candles["date"] = str(date) + + # resCandle.append(Candles) res.append((start,str(date))) xs.append(0) @@ -194,9 +228,7 @@ class Simulation: ys.append(rand_2[0]) poly = lagrange(xs, ys) func = Polynomial(poly.coef[::-1]) - new_points = func(np.array(echant_x)) - - + new_points = func(np.array(echant_x)) for i,p in enumerate(new_points): #print(f"Old : {p}") @@ -213,6 +245,7 @@ class Simulation: self.plotPrice(res) # self.plotPrice(res) + self.candle_prices = resCandle self.histo_prices = res #print(self.histo_prices) @@ -429,6 +462,10 @@ class Simulation: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) #add h_between to order ord["duration"] = m_between + ord["timeExit"] = self.histo_prices[cpt][1] + + # print("WinsAV : ",ord, histo_price) + # print("Date fin ? ",self.histo_prices[cpt][1]) self.winsAV.append([ord,histo_price]) #print(f"Winning cycle AV => Price Enter : {ord['price']} & Price Exit : {histo_price} & TP : {self.tp*100}% ") cycle_ended = True @@ -437,6 +474,7 @@ class Simulation: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) #add h_between to order ord["duration"] = m_between + ord["timeExit"] = self.histo_prices[cpt][1] self.lossAV.append([ord,histo_price]) #print(f"Loosing cycle AV => Price Enter : {ord['price']} & Price Exit : {histo_price} & SL : {self.sl*100}%") cycle_ended = True @@ -445,6 +483,7 @@ class Simulation: if cycle_ended == False: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) ord["duration"] = m_between + ord["timeExit"] = self.histo_prices[cpt][1] self.end_forced_cycle.append([ord,histo_price]) #print(f"24h Limit Passed AV => Price Enter : {ord['price']} & Price Exit : {histo_price}") return cpt @@ -475,6 +514,7 @@ class Simulation: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) #add h_between to order ord["duration"] = m_between + ord["timeExit"] = self.histo_prices[cpt][1] self.winsVA.append([ord,histo_price]) cycle_ended = True #print(f"Winning cycle VA => Price Enter : {ord['price']} & Price Exit : {histo_price} & TP : {self.tp*100}%") @@ -484,6 +524,8 @@ class Simulation: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) #add h_between to order ord["duration"] = m_between + ord["timeExit"] = self.histo_prices[cpt][1] + self.lossVA.append([ord,histo_price]) cycle_ended = True #print(f"Loosing cycle VA => Price Enter : {ord['price']} & Price Exit : {histo_price} & SL : {self.sl*100}%") @@ -493,6 +535,7 @@ class Simulation: if cycle_ended == False: m_between = self.minutesBetween(ord['date'],self.histo_prices[cpt][1]) #add h_between to order + ord["timeExit"] = self.histo_prices[cpt][1] ord["duration"] = m_between self.end_forced_cycle.append([ord,histo_price]) #print(f"Time Limit Passed VA => Price Enter : {ord['price']} & Price Exit : {histo_price}") diff --git a/main/templates/.DS_Store b/main/templates/.DS_Store index ffeff0bdc683e3f91e60a808a2bb555ca0786833..52dae881498cdd08ea8924467dd64fec2fc48175 100644 GIT binary patch delta 69 zcmZoMXfc=|#>CJ*u~2NHo+2aD!~pBb1|lqz`58?nmopk|e#WTCHu(eN$Ia{<{2WXS a?VBGmerKM{FJj2ZFxiGjdUK4(3T6P#OB8Vc delta 110 zcmZoMXfc=|#>B`mu~2NHo+2a5!~p9_j17z|6MM`#lNb^iiWyQFj3%CuVPXiFxXqrI zn<0}Sk0FI2m7#*cc;XpJ?)3}|3<3YaVB<$!w$1Du{2WY-92-A=XP(S2V#vYBz`)SJ Mz`(HCLu3y#0MPLuHUIzs diff --git a/main/templates/index.html b/main/templates/index.html index c11c932..7b7cb19 100644 --- a/main/templates/index.html +++ b/main/templates/index.html @@ -238,8 +238,7 @@ <div class="card shadow-2-strong card-registration" style="border-radius: 15px;"> <div class="card-body p-4"> <div class="row"> - <div id="chart"> - </div> + <div id="chart"></div> </div> <div class="row"> {% for symbol in res['profits'] %} @@ -384,9 +383,12 @@ </section> {% endif %} <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> -<script> +<script src="https://d3js.org/d3.v7.min.js"></script> +<script src="https://cdn.canvasjs.com/canvasjs.min.js"></script> +<script src="https://canvasjs.com/assets/script/jquery-1.11.1.min.js"></script> +<script> const showMoreInfo = document.getElementById('btnShowMoreInfo'); const indicatorSelect = document.getElementById('indicatorSelect'); @@ -397,8 +399,9 @@ var chart = null; {% if fig != None %} - var chart = {{ fig | safe }}; - Plotly.plot("chart", chart, {}); + chart = {{ fig | safe }}; + console.log(chart); + Plotly.plot("chart", chart, {}); {% endif %} if (!inProgress && chart == null) { diff --git a/main/templates/indexD3Chart.html b/main/templates/indexD3Chart.html new file mode 100644 index 0000000..a033fde --- /dev/null +++ b/main/templates/indexD3Chart.html @@ -0,0 +1,626 @@ +{% extends 'base.html' %} + +{% block content %} +{% if not inProgress and fig == None %} +<section class="gradient-custom p-5"> + <div class="container py-5 h-100"> + <div class="row justify-content-center align-items-center h-100"> + <div class="col-12 col-lg-9 col-xl-7"> + <div class="card shadow-2-strong card-registration" style="border-radius: 15px;"> + <div class="card-body p-4 p-md-5"> + <h3 class="mb-4 pb-2 pb-md-0 mb-md-2">Création d'une simulation</h3> + <form action="startSimulation" method="post"> + <div class="row"> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="takeProfit">Take profit %</label> + <input type="number" + class="form-control form-control-lg {{ err['takeProfit'] }}" id="takeProfit" + name="takeProfit" max="100.0" min="1.0" + value="{{ stickyForm['takeProfit'] }}" step="0.1" required> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer un nombre entre 1.0 et 100.0 + </div> + </div> + + </div> + <div class="col-md-6 mb-4"> + + <div class="form-outline"> + <label class="form-label" for="stopLoss">Stop Loss %</label> + <input type="number" class="form-control form-control-lg {{ err['stopLoss'] }}" + id="stopLoss" name="stopLoss" min="1.0" max="100.0" + value="{{ stickyForm['stopLoss'] }}" step="0.1" required> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer un nombre entre 1 et 100.0 + </div> + </div> + + </div> + + </div> + + <div class="row"> + <div class="col-md-6 mb-4 d-flex align-items-center"> + + <div class="form-outline datepicker w-100"> + <label for="dateSimStart" class="form-label">Date du début de la + simulation</label> + <input type="date" class="form-control form-control-lg {{ err['dateSim'] }}" + id="dateSimStart" name="dateSimStart" + value="{{ stickyForm['dateSimStart'] }}" min="2022-02-05" max="2022-04-09" + required> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer une date entre le 05/02/2022 et le 09/04/2022. La date du + début ne doit pas être plus grande que la date de la fin ou égale. + </div> + </div> + + </div> + <div class="col-md-6 mb-4"> + + <div class="form-outline datepicker w-100"> + <label for="dateSimEnd" class="form-label">Date de la fin de la + simulation</label> + <input type="date" class="form-control form-control-lg {{ err['dateSim'] }}" + id="dateSimEnd" name="dateSimEnd" value="{{ stickyForm['dateSimEnd'] }}" + min="2022-02-05" max="2022-04-09" required> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer une date entre le 05/02/2022 et le 09/04/2022. La date de la + fin ne doit pas être plus petite que la date du début ou égale. + </div> + + </div> + </div> + </div> + <div class="row"> + <!-- <div class="col-md-6 mb-4 pb-2"> + + <div class="form-outline"> + <label class="form-label" for="candleSize">Taille de la bougie</label> + <input type="number" class="form-control form-control-lg" id="candleSize" + name="candleSize" max="20" min="5" value="10" step="1"> + </div> + + </div> --> + <div class="mb-4 pb-2"> + + <div class="form-inline"> + <label class="form-label my-1 mr-2" for="indicator">Indicateur + technique</label> + <select class="form-control form-select {{ err['indicator'] }}" + name="indicatorSelect" id="indicatorSelect" required> + {% if stickyForm['indicatorSelect'] == '' %} + <option value="" selected disabled hidden>Sélectionner...</option> + {% endif %} + {% if stickyForm['indicatorSelect'] == 'SMA' %} + <option value="SMA" selected>Moyenne glissante</option> + {% else %} + <option value="SMA">Moyenne glissante</option> + {% endif %} + {% if stickyForm['indicatorSelect'] == 'random'%} + <option value="random" selected>Aléatoire</option> + {% else %} + <option value="random">Aléatoire</option> + {% endif %} + {% if stickyForm['indicatorSelect'] == 'test' %} + <option value="test" selected>test</option> + {% else %} + <option value="test">test</option> + {% endif %} + </select> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez sélectionner un indicateur de la liste. + </div> + </div> + + </div> + </div> + + <div class="row" id="rowSMA" style="display: none;"> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="MA1">Moyenne glissante courte</label> + <input type="number" class="form-control form-control-lg {{ err['ma'] }}" + id="MA1" name="MA1" max="100" min="5" value="{{ stickyForm['MA1'] }}" + step="5"> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer un nombre entre 5 et 100. La moyenne glissante courte + doit être plus petite que la longue. + </div> + </div> + </div> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="MA2">Moyenne glissante longue</label> + <input type="number" class="form-control form-control-lg {{ err['ma'] }}" + id="MA2" name="MA2" max="105" min="10" value="{{ stickyForm['MA2'] }}" + step="5"> + <div class="valid-feedback"> + Correct ! + </div> + <div class="invalid-feedback"> + Veuillez entrer un nombre entre 10 et 105. La moyenne glissante + longue doit être plus grande que la courte. + </div> + </div> + </div> + </div> + <div class="row" id="rowRandom" style="display: none;"> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="M">Random</label> + <input type="number" class="form-control form-control-lg" id="MA1" name="MA1" + max="100" min="5" value="20" step="5"> + </div> + + </div> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="M">Random</label> + <input type="number" class="form-control form-control-lg" id="MA2" name="MA2" + max="105" min="10" value="40" step="5"> + </div> + + </div> + </div> + <div class="row" id="rowTest" style="display: none;"> + <div class="col-md-6 mb-4"> + <div class="form-outline"> + <label class="form-label" for="M">Test 1</label> + <input type="number" class="form-control form-control-lg" id="MA1" name="MA1" + max="100" min="5" value="20" step="5"> + </div> + + </div> + <div class="col-md-6 mb-4"> + <label class="form-label" for="M">Test 2</label> + <div class="form-check form-switch"> + <input class="form-check-input" type="checkbox" id="flexSwitchCheckDefault"> + <label class="form-check-label" for="flexSwitchCheckDefault">Test</label> + </div> + + </div> + </div> + <div class="row text-center"> + <div class="mt-4 pt-2"> + <button type="submit" class="btn btn-primary btn-lg">Lancer la simulation</button> + </div> + </div> + </form> + </div> + </div> + </div> + </div> + </div> +</section> +{% endif %} +{% if inProgress %} +<section class="gradient-custom p-5 h-100 align-items-center my-auto"> + <div class="container py-5 h-100"> + <div class="row justify-content-center align-items-center h-100"> + <div class="col-12 col-lg-9 col-xl-7"> + <div class="card shadow-2-strong card-registration" style="border-radius: 15px;"> + <div class="card-body p-4 p-md-5"> + <div class="progress"> + <div class="progress-bar" id="progressBar" role="progressbar" aria-valuenow="0" + aria-valuemin="0" aria-valuemax="100" style="width:0%"></div> + </div> + </div> + </div> + </div> + </div> + </div> +</section> +{% endif %} +{% if fig != None %} +{% set moneySymbol = [] %} +<section class="gradient-custom p-5 h-100 align-items-center my-auto"> + <div class="container py-5 h-100"> + <div class="card shadow-2-strong card-registration" style="border-radius: 15px;"> + <div class="card-body p-4"> + <div class="row"> + <div id="candleChart"></div> + <div id="tooltip" style="position: absolute; opacity: 0;"></div> + </div> + <div class="row"> + {% for symbol in res['profits'] %} + {% set _ = moneySymbol.append(symbol) %} + <div class="col-md-6 mb-4 text-center"> + {% if symbol == "USDT" %} + <h1>{{ symbol }} : <span style="color:green"> +{{ res['moneyProfits'][symbol]|round(2)|string + }}₮ ({{ + res['profits'][symbol]|round(2)|string+"%" }})</span></h1> + {% elif symbol == "BTC" %} + <h1>{{ symbol }} : <span style="color:green"> +{{ + "{:.5f}".format(res['moneyProfits'][symbol])|string }}₿ ({{ + res['profits'][symbol]|round(2)|string+"%" }})</span></h1> + {% endif %} + </div> + {% endfor %} + {% for symbol in res['losses'] %} + {% set _ = moneySymbol.append(symbol) %} + <div class="col-md-6 mb-4 text-center"> + {% if symbol == "USDT" %} + <h1>{{ symbol }} : <span style="color:red">{{ res['moneyLosses'][symbol]|round(2)|string }}₮ ({{ + res['losses'][symbol]|round(2)|string+"%" }})</span></h1> + {% elif symbol == "BTC" %} + <h1>{{ symbol }} : <span style="color:red">{{ "{:.5f}".format(res['moneyLosses'][symbol])|string + }}₿ ({{ + res['losses'][symbol]|round(2)|string+"%" }})</span></h1> + {% endif %} + </div> + {% endfor %} + {% if res['profits'] == {} and res['losses'] == {} %} + <div class="text-center"> + <h1>Aucun résultats</h1> + <br> + </div> + {% endif %} + </div> + <div class="row align-items-center"> + <div class="col-sm mb-4 text-center"> + <button type="button" class="btn btn-secondary btn-lg" id="btnShowMoreInfo">Afficher plus de + résultats</button> + </div> + <div class="col-sm mb-4 text-center"> + <!-- Button trigger modal --> + <button type="button" class="btn btn-primary btn-lg" data-bs-toggle="modal" + data-bs-target="#modalSimulation"> + Démarrer une nouvelle simulation + </button> + + <!-- Modal --> + <div class="modal fade" id="modalSimulation" tabindex="-1" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title">Nouvelle simulation</h5> + <button type="button" class="btn-close" data-bs-dismiss="modal" + aria-label="Fermer"></button> + </div> + <div class="modal-body"> + <div class="row"> + <div class="col-sm mb-4 text-center"> + <a href="resetSimulation"> + <button type="button" class="btn btn-primary btn-lg">Restaurer les + valeurs par défaut</button></a> + <br> + <br> + <a href="resetSimulationWithParams"> + <button type="button" class="btn btn-primary btn-lg">Modifier les + anciennes valeurs</button></a> + </div> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" + data-bs-dismiss="modal">Fermer</button> + </div> + </div> + </div> + </div> + </div> + <div class="col-sm mb-4 text-center"> + <button type="button" class="btn btn-success btn-lg"> + Enregistrer la simulation <i class="bi bi-save"></i> + </button> + </div> + </div> + <div id="moreResults" style="display: none;"> + <div class="row pt-3 mb-3 border-top"> + <div class="col-sm text-center"> + <h4>Balance avant</h4> + </div> + {% for i in moneySymbol %} + <div class="col-sm text-center"> + {% if i == "USDT" %} + <h4>{{ res['startBalance'][i] }}₮</h4> + {% elif i == "BTC" %} + <h4>{{res['startBalance'][i] }}₿ </h4> + {% endif %} + </div> + {% endfor %} + </div> + <div class="row pt-3 mb-3 border-top"> + <div class="col-sm text-center"> + <h4>Balance après</h4> + </div> + {% for i in res['profits'] %} + <div class="col-sm text-center"> + {% if i == "USDT" %} + <h4>{{ res['startBalance'][i] + res['moneyProfits'][i]}}₮</h4> + {% elif i == "BTC" %} + <h4>{{"{:.5f}".format(res['startBalance'][i] + res['moneyProfits'][i])}}₿ </h4> + {% endif %} + </div> + {% endfor %} + {% for i in res['losses'] %} + <div class="col-sm text-center"> + {% if i == "USDT" %} + <h4>{{ res['startBalance'][i] + res['moneyLosses'][i]}}₮</h4> + {% elif i == "BTC" %} + <h4>{{"{:.5f}".format(res['startBalance'][i] + res['moneyLosses'][i])}}₿ </h4> + {% endif %} + </div> + {% endfor %} + </div> + <div class="row pt-3 mb-3 border-top"> + <div class="col-sm text-center"> + <h5>Nombre d'ordres gagants : {{ res['nbWins'] }}</h5> + </div> + <div class="col-sm text-center"> + <h5>Nombre d'ordres perdants : {{ res['nbLosses'] }}</h5> + </div> + <div class="col-sm text-center"> + <h5>Nombre total d'ordres : {{ res['totalTrades'] }}</h5> + </div> + <div class="col-sm text-center"> + <h5>Pourcentage de réussite : {{ res['winrate'] }}%</h5> + </div> + </div> + </div> + </div> + </div> + </div> +</section> +{% endif %} +<script src="https://cdn.plot.ly/plotly-latest.min.js"></script> +<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> +<script src="https://www.chartjs.org/chartjs-chart-financial/chartjs-chart-financial.js"></script> +<script src="https://cdn.jsdelivr.net/npm/luxon@1.26.0"></script> +<script src="https://cdn.jsdelivr.net/npm/chart.js@3.0.1/dist/chart.js"></script> +<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@1.0.0"></script> +<script src="https://www.chartjs.org/chartjs-chart-financial/chartjs-chart-financial.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script> +<script src="https://d3js.org/d3.v7.min.js"></script> +{% if fig != None %} +<script> + function getRandomArbitrary(min, max) { + return Math.random() * (max - min) + min; + } + + var data = {{ fig | safe }} + console.log(data) + var baseValue = 100; + var baseDate = new Date(data[0].date); + + console.log(data.length) + data.forEach(function (d) { + d.date = new Date(d.date); + }); + + + var margin = { top: 20, right: 50, bottom: 30, left: 50 }, + width = 960 - margin.left - margin.right, + height = 500 - margin.top - margin.bottom; + var barWidth = Math.floor(width / data.length); + + var x = d3.scaleTime() + .domain(d3.extent(data, d => d.date)) + .range([0, width]); + + var y = d3.scaleLinear() + .domain([d3.min(data, d => d.low), d3.max(data, d => d.high)]) + .range([height, 0]); + + var svg = d3.select("#candleChart").append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + svg.append("rect") + .attr("width", width) + .attr("height", height) + .style("fill", "none") + .style("pointer-events", "all"); + + + var barWidth = Math.floor(width / data.length); + + var xAxis = d3.axisBottom(x); + + var yAxis = d3.axisLeft(y); + + // Ajouter les axes au SVG + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(xAxis); + + svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + // Définir la fonction de zoom + //var barWidth = 15; // Largeur des bougies en pixels + + var zoom = d3.zoom() + .scaleExtent([1, 100]) // Zoom limité entre 1x et 100x + .extent([[0, 0], [width, height]]) + .on("zoom", function (event) { + // Mettre à jour les échelles + var new_xScale = event.transform.rescaleX(x); + + // Calculer la nouvelle largeur des bougies + var t = event.transform, + xt = t.rescaleX(x); + + // Si le zoom est au maximum + if (t.k === 100) { // 100 est le niveau de zoom maximum défini par scaleExtent([1, 100]) + var firstDate = data[0].date; + var lastDate = new Date(firstDate.getTime() + 15 * 60 * 1000); // 15 minutes plus tard + xt.domain([firstDate, lastDate]); + } + + barWidth = Math.max(1, Math.min(barWidth, width / xt.domain().length)); + + // Mettre à jour les bougies et les tiges + svg.selectAll("rect.candle") + .attr("x", d => xt(d.date) - 0.5 * barWidth) + .attr("width", barWidth); + svg.selectAll("line.stem") + .attr("x1", d => xt(d.date)) + .attr("x2", d => xt(d.date)); + + // Appeler les axes sur leurs sélections respectives + svg.select(".x.axis").call(xAxis.scale(new_xScale)); + svg.select(".y.axis").call(yAxis); + }); + + + function zoomed({ transform }) { + svg.attr("transform", transform); + } + + svg.call(zoom); + + svg.selectAll("line.stem") + .data(data) + .enter().append("line") + .attr("class", "stem") + .attr("x1", d => x(d.date)) + .attr("x2", d => x(d.date)) + .attr("y1", d => y(d.high)) + .attr("y2", d => y(d.low)) + .attr("stroke", d => d.open === d.close ? "darkgrey" : d.open > d.close ? "red" : "green"); + + svg.selectAll("rect.candle") + .data(data) + .enter().append("rect") + .attr("class", "candle") + .attr("x", d => x(d.date) - 0.5 * barWidth) + .attr("y", d => y(Math.max(d.open, d.close))) + .attr("width", barWidth) + .attr("height", d => y(Math.min(d.open, d.close)) - y(Math.max(d.open, d.close))) + .attr("fill", d => d.open === d.close ? "darkgrey" : d.open > d.close ? "red" : "green"); + + + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(x)); + + svg.append("g") + .attr("class", "y axis") + .call(d3.axisLeft(y)); + + + // Ajouter un événement mouseover à chaque bougie + svg.selectAll("rect.candle") + .on("mouseover", function (event, d) { + // Changer l'opacité de l'infobulle + d3.select("#tooltip").style("opacity", 1); + + // Changer le texte de l'infobulle + d3.select("#tooltip").html( + "Date: " + d.date.toISOString() + "<br/>" + + "Open: " + d.open.toFixed(2) + "<br/>" + + "Close: " + d.close.toFixed(2) + "<br/>" + + "High: " + d.high.toFixed(2) + "<br/>" + + "Low: " + d.low.toFixed(2) + ) + }) + .on("mousemove", function (event, d) { + // Déplacer l'infobulle + d3.select("#tooltip") + .style("left", (event.pageX + 10) + "px") + .style("top", (event.pageY - 10) + "px"); + }) + .on("mouseout", function (event, d) { + // Cacher l'infobulle + d3.select("#tooltip").style("opacity", 0); + }); + +</script> +{% endif %} + +<script> + const showMoreInfo = document.getElementById('btnShowMoreInfo'); + + const indicatorSelect = document.getElementById('indicatorSelect'); + const SMA = document.getElementById('rowSMA'); + const random = document.getElementById('rowRandom'); + const test = document.getElementById('rowTest'); + var inProgress = {{ inProgress| lower }}; + var chart = null; + //var chartData = {{ fig | safe }}; + + {% if fig != None %} + chart = {{ fig | safe }}; + //var chart = {{ fig | safe }}; + //Plotly.plot("chart", chart, {}); + {% endif %} + + if (!inProgress && chart == null) { + indicatorChange(); + indicatorSelect.addEventListener('change', indicatorChange); + } + if (inProgress) { + updateProgressBar(); + } + + + {% if fig != None %} + showMoreInfo.addEventListener('click', function () { + if (moreResults.style.display === 'none') { + moreResults.style.display = 'block'; + showMoreInfo.innerHTML = 'Masquer les résultats'; + } else { + moreResults.style.display = 'none'; + showMoreInfo.innerHTML = 'Afficher plus de résultats'; + } + }); + {% endif %} + + function updateProgressBar() { + $.ajax({ + url: '/progress', + success: function (data) { + var progress = data.progress; + $('#progressBar').css('width', progress + '%'); + if (progress === 100) { + location.reload(); + } else { + setTimeout(updateProgressBar, 1000); + } + } + }); + } + + function indicatorChange() { + if (indicatorSelect.value === 'SMA') { + SMA.style.display = 'flex'; + random.style.display = 'none'; + test.style.display = 'none'; + } else if (indicatorSelect.value === 'random') { + random.style.display = 'flex'; + SMA.style.display = 'none'; + test.style.display = 'none'; + } else if (indicatorSelect.value === 'test') { + test.style.display = 'flex'; + SMA.style.display = 'none'; + random.style.display = 'none'; + } + } +</script> +{% endblock %} \ No newline at end of file -- GitLab