1

This file is called 'html app.py'

from flask import Flask, render_template, request
import yfinance as yf
import seaborn as sns
import matplotlib.pyplot as plt
import io
import base64

app = Flask(__name__)

@app.route('/')
def welcome():
    return render_template("signInor Login.html")


@app.route('/submit', methods=["POST"] )
def submit():
    username = request.form.get('username')
    password = request.form.get('password')
    if username== "rashmip_21" and password=='fabulousRashmi':
        return render_template("home.html")
    else:
        return "Invalid Credenials"
    
#@app.route('/goToSMA', methods = ["POST"])
#def gotosma():
#    return render_template("Simple Moving Average.html")
    
@app.route('/sma', methods=["POST"] )
def sma():
    ticker_symbol = request.form.get('tickersym')
    start_date = request.form.get('start')
    end_date = request.form.get('end')
    wind_td = request.form.get('windtd')
    df=yf.download(ticker_symbol)
    df['Simple Moving Average']= df['Close'].rolling(window=wind_td).mean()
    sns.lineplot(x='Date',y='Close',data=df.droplevel(1,axis=1),label="Close")
    sns.lineplot(x='Date',y='Simple Moving Average',data=df.droplevel(1,axis=1),label="S.M.A.")
    plt.xlabel("Date")
    plt.ylabel("Average/Close")
    
app.run(debug=True)

This is 'home.html'

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vizly.welcome</title>
</head>
<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='styles/styleHome.css')}}">

<body id="bodyWelcome" style="background-color: #b8e0fc;">
    <nav class="navbar">
        <ul>
            <img src="{{url_for('static',filename='styles/logo.png')}}" id="logo">
            <li><a href="">About Us</a></li>
            <li><a href="">Sign In / Login</a></li>
            <li><!--<a href="">Stock Data</a>-->
                <div class="drop">
                    <button class="dropbtn">Stock Data</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Ticker Symbol</a>
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                    </div>
                </div>
            </li>
            <li>
                <div class="drop">
                    <button class="dropbtn">Visualize</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                        <a href="">Bollinger's Band</a>
                        <a href="">Candlestick Graph</a>
                    </div>
                </div>
                
            </li>
            <li><a href="">Home</a></li>
        </ul>
    </nav>
    <p>Do you want to calculate the Simple Moving Average or the Exponential moving average for some historical data? All you need to do is enter the Ticker symbol, the start and end dates and the number of trading days.</p>
    <div class="flex-container">
        <div class="flex-box"><a href="">Simple Moving Average</a></div>
        <div class="flex-box"><a href="">Exponential Moving Average</a></div>
    </div>
    <p>Or do you want to visualize the Simple Moving Average, Exponential Moving Average, Bollinger's Band or Candlestick chart?  Again all you need to do is enter the Ticker symbol, the start and end dates and the number of trading days.</p>
    <div class="flex-container">
        <div class="flex-box" ><a href="Simple Moving Average.html">SMA Visualizer</a></div>
        
        <div class="flex-box"><a href="">EMA Visualizer</a></div>
        <div class="flex-box"><a href="">Bollinger's Band Visualizer</a></div>
        <div class="flex-box"><a href="">Candlestick Chart</a></div>
    </div>
</body>

</html>

This is welcome.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vizly.welcome</title>
</head>
<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='styles/styleWelcome.css')}}">

<body id="bodyWelcome" style="background-color: #b8e0fc;">
    <nav class="navbar">
        <ul>
            <img src="{{url_for('static',filename='styles/logo.png')}}" id="logo">
            <li><a href="">About Us</a></li>
            <li><a href="">Sign In / Login</a></li>
            <li><!--<a href="">Stock Data</a>-->
                <div class="drop">
                    <button class="dropbtn">Stock Data</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Ticker Symbol</a>
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                    </div>
                </div>
            </li>
            <li>
                <div class="drop">
                    <button class="dropbtn">Visualize</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                        <a href="">Bollinger's Band</a>
                        <a href="">Candlestick Graph</a>
                    </div>
                </div>

            </li>
            <li><a href="home.html">Home</a></li>
        </ul>
    </nav>
    <h1>Welcome to Vizly!</h1>
    <h5>Analyze, Visualize, Understand.</h5>
    <p>Welcome to Vizly - the Stock Market Visualizer! This tool provides insightful analysis and visualization of
        historical stock data, helping you understand market trends and make informed decisions.</p>
    <p>Leverage the power of data to explore stock performance. Input any ticker symbol and date range to generate
        detailed charts and key financial indicators.</p>

</body>

</html>

This is Simple Moving Average.html

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script type="module" src="https://pyscript.net/releases/2024.2.1/core.js"></script>
    <link rel="stylesheet" href="https://pyscript.net/releases/2025.7.3/core.css" />
    <title>Simple Moving Average</title>

</head>


<link rel="stylesheet" type="text/css" href="{{url_for('static',filename='styles/styleSMA.css')}}">

<body id="bodyWelcome" style="background-color: #b8e0fc;">
    <nav class="navbar">
        <ul>
            <img src="{{url_for('static',filename='styles/logo.png')}}" id="logo">
            <li><a href="">About Us</a></li>
            <li><a href="">Sign In / Login</a></li>
            <li><!--<a href="">Stock Data</a>-->
                <div class="drop">
                    <button class="dropbtn">Stock Data</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Ticker Symbol</a>
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                    </div>
                </div>
            </li>
            <li>
                <div class="drop">
                    <button class="dropbtn">Visualize</button>
                    <!--<a href="">Visualize</a>-->
                    <div class="drop-down">
                        <a href="">Simple Moving Average</a>
                        <a href="">Exponential Moving Average</a>
                        <a href="">Bollinger's Band</a>
                        <a href="">Candlestick Graph</a>
                    </div>
                </div>

            </li>
            <li><a href="">Home</a></li>
        </ul>
    </nav>
    <form method="POST" action="/sma">
        <label for="tickersym">Enter ticker symbol:</label>
        <input type="text" name="tickersym" id="tickersym">
        <br>
        <label for="start"> Enter start date:</label>
        <input type="date" name="start" id="start"><br>
        <label for="end">Enter end date:</label>
        <input type="date" name="end" id="end"><br>
        <label for="windtd">Enter number of trading days (window) for SMA:</label>
        <input type="number" name="windtd" id="windtd"><br>

        <button type="button" name="calculate" id="calculate">Calculate SMA</button>
        <button type="button" name="refresh" id="refresh">Refresh</button>
    </form>
    
</body>

</html>

I want the user to input the ticker symbol, start date, end date, and window to the website. Then I want to fetch the historical stock data from yfinance and plot the SMA graph using seaborn and matplotlib. However, I am neither able to go to the 'simple moving average' page from the 'home' page, nor am I able to return the graph to the website. Please help. I have used the necessary CSS.

5
  • Please write what error message, if any, you're getting. Commented Jul 26 at 13:29
  • @JonathanCiapetti I am not getting any error actually. Commented Jul 26 at 13:52
  • Not even a 404? Commented Jul 26 at 13:52
  • No. Actually I just wrote a simple python code with plt.show() and it showed no error later I just removed that line to try out different solutions. But now it is the original code I wrote and I am sorry I forget to add the 'plt.show()' line at the end. Commented Jul 26 at 14:46
  • However on trying to access the SMA page it gives the error "Method Not Allowed The method is not allowed for the requested URL" Commented Jul 26 at 14:48

3 Answers 3

1

If you can't access the SMA page, it's because the POST method is defined for the associated route, and a simple call in the browser sends a GET request. Only when submitting form data, if the POST method is explicitly defined, does the browser send a request of this type, with the data being submitted in the request body. You've already used this method for your login.

However, I suggest using the GET method to submit the form data for the chart. This way, the data is appended to the URL as a URL parameter.

The difference is essentially the visibility for third parties.

The following example uses plotly instead of seaborn and matplotlib, but may help you develop your application. Keep in mind that, as far as I know, matplotlib is only transmitted to the browser as a static image, while plotly displays a chart with which the user can interact. Furthermore, the code shows you how to send form data to the server using both of these methods.

''' 
$ pip install flask yfinance plotly
'''

from datetime import date, timedelta
from flask import (
    Flask, 
    redirect, 
    render_template, 
    request, 
    session, 
    url_for
)
import yfinance as yf
import plotly
import plotly.graph_objects as go

app = Flask(__name__)
app.secret_key='your secret here'

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        if username == 'user' and password == 'pass':
            session['user'] = 'user'
            return redirect(url_for('stocks'))
    return render_template('index.html', **locals())

@app.route('/stocks')
def stocks():
    if 'user' not in session:
        return redirect(url_for('index'))

    symbol = request.args.get('sym', 'AAPL')
    bgn_dt = request.args.get('bgn', date.today() - timedelta(weeks=4), type=lambda x: date.fromisoformat(x))
    end_dt = request.args.get('end', date.today(), type=lambda x: date.fromisoformat(x))

    ticker = yf.Ticker(symbol)
    df = ticker.history(start=bgn_dt.isoformat(), end=end_dt.isoformat())

    fig = go.Figure()
    fig.add_trace(go.Candlestick(
            x=df.index,
            open=df['Open'],
            high=df['High'],
            low=df['Low'],
            close=df['Close']
        )
    )
    fig.add_trace(go.Scatter(
            x=df.index, 
            y=df['Close'], 
            mode='lines', 
            name='Close', 
            line=dict(color="#444")
        )
    )
    fig.update_layout(
        autotypenumbers='convert types', 
        title=f'{symbol} Chart',
        yaxis_title='Price (USD)',
        xaxis_title='Date', 
        xaxis_rangeslider_visible=False, 
    )
    fig.update_yaxes(tickprefix="$")
    fig.update_xaxes(
        dtick='D1',
        tickformat="%d.%m.%Y"
    )
    fig.update_xaxes(type='date')

    data = fig.to_json()
    
    return render_template('stocks.html', **locals())
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Index</title>
</head>
<body>
    <form method="POST">
        <div>
            <label for="username">Username</label>
            <input type="text" name="username" id="username" />
        </div>
        <div>
            <label for="password">Password</label>
            <input type="password" name="password" id="password" />
        </div>
        <button type="submit">Login</button>
    </form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Stocks</title>
</head>
<body>
    <form>
        <div>
            <label for="ticker">Ticker</label>
            <input type="text" name="sym" id="ticker" value="{{symbol}}" />
        </div>
        <div>
            <label for="start">Start</label>
            <input type="date" name="bgn" id="start" value="{{bgn_dt}}" />
        </div>
        <div>
            <label for="end">End</label>
            <input type="date" name="end" id="end" value="{{end_dt}}" />
        </div>
        <button type="submit">Submit</button>
    </form>
    <hr />
    <div id="chart" class="chart"></div>

    <script src="https://cdn.plot.ly/plotly-3.0.1.min.js" charset="utf-8"></script>
    <script type='text/javascript'>
        (function() {
            const graphs = {{data | safe}};
            console.log(graphs.data, graphs.layout)
            Plotly.newPlot('chart', graphs.data, graphs.layout);
        })();
    </script>
</body>
</html>
Sign up to request clarification or add additional context in comments.

Comments

0

You have to create an html file which will get all the inputs that are going to be passed in the arguments of your post api then that api is going to process all the data and return the data which is going to be used in the graph. you can see these posts How can I get the named parameters from a URL using Flask? and docs https://flask.palletsprojects.com/en/stable/templating/

Comments

0

Here, you have allowed only POST for the /sma route:

@app.route('/sma', methods=["POST"] )
def sma():
    # ...

And Flask is telling you that the GET method is not allowed (error 405), because you have not provided a route for that. So first, add GET to the methods handled by the /sma route (you can also put that code in a separate endpoint):

@app.route('/sma', methods=["GET", "POST"] )
def sma():

    if request.method == "GET":
        return render_template("Simple Moving Average.html")

    elif request.method == "POST":
        ticker_symbol = request.form.get('tickersym')
        start_date = request.form.get('start')
        end_date = request.form.get('end')
        wind_td = request.form.get('windtd')
        df=yf.download(ticker_symbol)
        df['Simple Moving Average']= df['Close'].rolling(window=wind_td).mean()
        sns.lineplot(x='Date',y='Close',data=df.droplevel(1,axis=1),label="Close")
        sns.lineplot(x='Date',y='Simple Moving Average',data=df.droplevel(1,axis=1),label="S.M.A.")
        plt.xlabel("Date")
        plt.ylabel("Average/Close")

    # Store the plot in a variable, so that you can pass it to the template later; it's beyond
    # the scope of this question so I'm skipping the code, read how to do it in case of plots:
        # plot_data = ...

        return render_template("sma_result.html", plot_data=plot_data)

Also, in Simple Moving Average.html you're not using type=submit on your calculate button, so your form doesn't trigger any POST. This unless you have some JavaScript callback handling that button.

A small suggestion: as it is designed now (fixes aside), your code returns the template from the POST, and that can be a problem because if a user reloads the page, on every reload the browser will send a POST request. To solve this, you can implement the POST-Redirect-GET pattern, which prevents those re-submissions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.