Home > Mobile >  Refreshing Plotly Candlestick Plot in Flask App
Refreshing Plotly Candlestick Plot in Flask App

Time:03-28

I am plotting candlestick plot using plotly. I am getting the data from yahoo finance and is being refreshed every minute. Below code generates the plot and saves it in HTML format, till this point I am able to do successfully.

Code to generate plot (file is named as get_VIP_graph_html.py):

import pandas as pd
import plotly.offline as po
import plotly.graph_objs as go
import yfinance as yf


def get_graph():
    
    try:
        
        sid = "VIPIND.NS"
        df = yf.download(tickers=sid,interval="1m", period="1d")
        df.reset_index(inplace = True)
        df['Datetime'] = df['Datetime'].dt.tz_convert('Asia/Kolkata').dt.tz_localize(None)
        df['Datetime'] = pd.to_datetime(df['Datetime'])
        df=df.set_index('Datetime')
        df=df.tail(70)

        trace = go.Candlestick(x=df.index,open=df['Open'],high=df['High'],low=df['Low'],close=df['Close'],
                               name = 'sid')
        
        data = [trace]
        
        layout = {'title': sid}
        fig = dict(data=data, layout=layout)
        po.plot(fig, filename='templates/stock.html',auto_open=False)
        
        return True

    except:
        return False 

Below is my flask App code (file is named as view.py):

from flask import render_template, Flask, request
from get_VIP_graph_html import get_graph

app = Flask(__name__)

@app.route('/', methods=["POST", "GET"])
def homepage():
    
    try:
        result = get_graph() #start
        if result == True:
            return render_template("main.html")
        else:
            return render_template('main.html', sign='Chart Not Generated')
        
    except Exception as e:
        return render_template("main.html", sign=e)
    
if __name__ == '__main__':
    app.run(debug=True,port=8052)

Now is my code for main.html template.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
    <title>stock-graph</title>

<!--Bootstrap core CSS -->
    <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
    <!--Bootstrap core js-->
    <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
 </head>

<body>
 <div >
    <!--Data form-->
    <h1 align="center">Candlestick Chart With Technical Analysis</h1>
    {% include 'stock.html' %}


  </div>
 </body>
<script>
setInterval(function() {
fetch('/')
},60000
);
</script>
</html>

The stock.html which is being generated with plotly plot is been embedded into main.html using

{% include 'stock.html' %}

I am using setInterval function to run view.py again which is extracting latest data by executing the same every 1min. Screenshot below shows the same:

enter image description here

But still the plot is not getting refreshed. Somehow the latest stock.html file is not getting loaded into main.html during refresh.

How should I fix this issue, where I am I going wrong.

Appreciating your time and efforts.

Sudhir

CodePudding user response:

Using a different approach

  • don't save HTML, send figure definition
  • use AJAX for updates, then flask is called at defined interval
  • have set interval low for testing purposes. Have left console.log() in place for debug purposes
  • important that dates are formatting for auto-conversion between python and javascript

app.py

from get_VIP_graph import get_graph
from flask import Flask, render_template, Response, jsonify

app = Flask(__name__)

@app.route('/')
@app.route('/home')
def home():
    return render_template('main.html')


@app.route('/fig')
def fig():
    return jsonify(get_graph())

if __name__ == '__main__':
    app.run(debug=True, port=3000)


get_VIP_graph.py

import yfinance as yf
import pandas as pd
import plotly.graph_objects as go


def get_graph():
    sid = "VIPIND.NS"
    df = yf.download(tickers=sid, interval="1m", period="1d")
    df.reset_index(inplace=True)
    df["Datetime"] = df["Datetime"].dt.tz_convert("Asia/Kolkata").dt.tz_localize(None)
    df["Datetime"] = pd.to_datetime(df["Datetime"])
    df = df.set_index("Datetime")
    df = df.tail(70)

    # make sure everything is json serializable, plus use  ISO 8601 for dates
    trace = go.Candlestick(
        x=df.index.strftime('%Y-%m-%dT%H:%M:%SZ').tolist(),
        open=df["Open"].tolist(),
        high=df["High"].tolist(),
        low=df["Low"].tolist(),
        close=df["Close"].tolist(),
        name="sid",
    )

    data = [trace]

    layout = {"title": sid}
    fig = dict(data=data, layout=layout)

    return go.Figure(fig).to_dict()

if __name__ == '__main__':
    print(get_graph())

main.html

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <!-- <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}"> -->
    <title>stock-graph</title>

    <!--Bootstrap core CSS -->
    <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
    <!--Bootstrap core js-->
    <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <script src="https://cdn.plot.ly/plotly-2.9.0.min.js"></script>
</head>

<body>
    <div >
        <!--Data form-->
        <h1 align="center">Candlestick Chart With Technical Analysis</h1>
        <div id="graph" />


    </div>
</body>
<script>
    function apicall(url) {
        $.ajax({
            type:"GET", url:url, 
            success: (data) => { 
                console.log(data, $("#graph"));
                Plotly.newPlot( $("#graph")[0], data );
             }
        });
    }
    window.onload = function () {
        apicall("/fig");
    }

    setInterval(function() {apicall("/fig");},1000);

</script>

</html>
  • Related