Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
holoviz
GitHub Repository: holoviz/panel
Path: blob/main/doc/explanation/api/examples/stocks_declarative.md
2014 views

Stock Explorer - Declarative API

Before launching into the application code we will first declare some components of the app that will be shared, including the title of the app, a set of stock tickers, a function to return a dataframe given the stock ticker and the rolling mean window_size, and another function to return a plot given those same inputs:

import panel as pn import pandas as pd import altair as alt import plotly.graph_objects as go from bokeh.sampledata import stocks from matplotlib.figure import Figure pn.extension('plotly', 'vega', template='bootstrap') import hvplot.pandas tickers = ['AAPL', 'FB', 'GOOG', 'IBM', 'MSFT'] def get_df(ticker, window_size): df = pd.DataFrame(getattr(stocks, ticker)) df['date'] = pd.to_datetime(df.date) return df.set_index('date').rolling(window=window_size).mean().reset_index() def get_altair(ticker, window_size): df = get_df(ticker, window_size) return alt.Chart(df).mark_line().encode(x='date', y='close').properties( width="container", height=400 ) def get_hvplot(ticker, window_size): df = get_df(ticker, window_size) return df.hvplot.line('date', 'close', grid=True, responsive=True, height=400) def get_mpl(ticker, window_size): fig = Figure(figsize=(10, 6)) ax = fig.subplots() df = get_df(ticker, window_size) df.plot.line('date', 'close', ax=ax) return fig def get_plotly(ticker, window_size): df = get_df(ticker, window_size) return go.Scatter(x=df.date, y=df.close) plot_fns = { 'altair': get_altair, 'hvplot': get_hvplot, 'matplotlib': get_mpl, 'plotly': get_plotly }

This example demonstrates how APIs in Panel differ, to see the same app implemented using a different API visit:

The declarative API expresses the app entirely as a single Parameterized class with parameters to declare the inputs, rather than explicit widgets. The parameters are independent of any GUI code, which can be important for maintaining large codebases, with parameters and functionality defined separately from any GUI or panel code. Once again the depends decorator is used to express the dependencies, but in this case the dependencies are expressed as strings referencing class parameters, not parameters of widgets. The parameters and the plot method can then be laid out independently, with Panel used only for this very last step.

import param class StockExplorer(param.Parameterized): backend = param.Selector(objects=plot_fns) ticker = param.Selector(objects=tickers) window_size = param.Integer(default=6, bounds=(1, 21)) @param.depends('backend', 'ticker', 'window_size') def plot(self): return self.backend(self.ticker, self.window_size) explorer = StockExplorer() pn.Row( pn.Column(explorer.param), pn.panel(explorer.plot, sizing_mode='stretch_width'), ).servable()