Sample PixieApp that provides Stock Ticker information


In [ ]:
import pandas as pd
import json
from pandas_datareader import data
from datetime import datetime, timedelta
from pixiedust.display.app import *

@PixieApp
class StockViewer():
    """
    Sample Stock Viewer PixieApp with live quotes
    """
    
    def setup(self):
        self.tickers = {}
        self.start = datetime(2014,1,1)
        self.end = datetime.today()
        self.show = "table"
        self.measurements = ["Open", "Close", "High", "Low", "Volume"]
        self.sel_measurement = self.measurements[0]
        self.dateranges = [(30,"1M"), (90,"3M"), (180,"6M"), (365,"1Y"), (730,"2Y")]
        self.sel_daterange = self.dateranges[0][0]
        self.pixieapp_entity = None
        self.provider = "yahoo"
        self.providers = ["google", "yahoo", "yahoo-actions", "yahoo-dividends", "enigma", "fred", 
                          "famafrench", "oecd", "eurostat", "edga-index", "nasdaq", "quandl"]
        
    def enable_ticker(self, ticker, enable):
        if ticker in self.tickers:
            self.tickers[ticker]["enable"] = (enable == "true")
            self.updatePDF()
            
    def update_measurement(self, measurement):
        self.sel_measurement=measurement
        self.updatePDF()
        
    def update_daterange(self, daterange):
        self.sel_daterange=daterange
        self.updatePDF()
        
    def update_provider(self, provider):
        self.provider = provider
        #rebuild all ticker dataframes
        self.pixieapp_entity = None
        for ticker in self.tickers:
            self.add_ticker(ticker)
            
    def updatePDF(self):
        df = pd.DataFrame({k: v['pdf'][self.sel_measurement] for k,v in self.tickers.items() if v['enable'] is True})
        self.pixieapp_entity = df[(datetime.today()-timedelta(days=self.sel_daterange)):datetime.today()]
        self.pixieapp_entity.reset_index(inplace=True)

    def add_ticker(self, ticker):
        try:
            self.tickers[ticker] = {
                "pdf" : data.DataReader(ticker,self.provider,self.start,self.end),
                "enable": True,
                "exception":None
            }
            self.updatePDF()
            print("Successfully added {}.".format(ticker))
        except Exception as exc:
            self.tickers[ticker]["exception"] = exc
            print("Ticker not found. Please enter a valid ticker. {}".format(exc))
        
    @route(tickersList="*")
    def tickers_list(self):
        return """
        {%for ticker in this.tickers%}
        <input type="checkbox" checked id="{{ticker}}{{prefix}}" 
            pd_script="self.enable_ticker('{{ticker}}', '$val({{ticker}}{{prefix}})')"
            pd_refresh="target{{prefix}}">
            {{ticker}}
        {%endfor%}
        """
    
    def get_pd_options(self):
        ret_value = {
            "noChartCache": "true"
        }
        if self.show == "table":
            ret_value.update({
                "handlerId":"dataframe" 
            })
        else:
            ret_value.update({
                "handlerId": "lineChart",
                "keyFields": "Date",
                "aggregation": "SUM",
                "rowCount":"1000",
                "timeseries":"true",
                "valueFields":",".join(list(self.tickers.keys()))
            })
        return json.dumps(ret_value)
    
    @route(tickersContent="*")
    def tickers_content(self):
        if self.pixieapp_entity is None:
            return "<div/>"
    
        return """
<div pd_entity pd_render_onload>
    <pd_options>
        {{this.get_pd_options()}}
    </pd_options>
</div>
        """

    @route()
    def default(self):         
        return """
<div class="row">
    <center>
    <label>Provider:</label>
    <select id="provider{{prefix}}" pd_script="self.update_provider('$val(provider{{prefix}})')" pd_refresh="target{{prefix}}">
        {%for provider in this.providers %}
            <option {%if provider==this.provider%}selected{%endif%} value="{{provider}}">{{provider}}</option>
        {%endfor%}
    </select>
    </center>
</div>
<div class="row">
    <div class="form-group col-sm-2" style="padding-right:10px;">
        <p>
        <label>1. Add tickers</label>
        </p>
        
        <p>
        <input id="t" name="tickerInput">
        </p>
        
        <p>
        <button type="submit" id="check" pd_script="self.add_ticker('$val(t)')" pd_refresh="tickersList{{prefix}},target{{prefix}}">
            Add 
        </button>
        </p>
        
        <p>
        <label>2. Select measurement, date range</label>
        </p>
        
        <p>
        <select id="measurement{{prefix}}" pd_model="measurement"
            pd_script="self.update_measurement('$val(measurement{{prefix}})')" pd_refresh="target{{prefix}}">
            {%for measurement in this.measurements %}
                <option value="{{measurement}}">{{measurement}}</option>
            {%endfor%}
        </select>
        </p>
        
        <p>
        <select id="dateRange{{prefix}}"
            pd_script="self.update_daterange($val(dateRange{{prefix}}))" pd_refresh="target{{prefix}}">
            {%for daterange in this.dateranges %}
                <option value="{{daterange[0]}}">{{daterange[1]}}</option>
            {%endfor%}
        </select>
        </p>
        
        <p>
        <label>3. Visualize</label>
        </p>        
        
        <p>
        <button type="submit" class="btn btn-primary" pd_refresh="target{{prefix}}" pd_script="self.show='table'">
            Preview as nice table
        </button>
        </p>
        
        <p>
        <button type="submit" class="btn btn-primary" pd_refresh="target{{prefix}}" pd_script="self.show='line'">
            Line chart
        </button>
        </p>
        
    </div>
    
    <div class="form-group col-sm-4 no_loading_msg" id="tickersList{{prefix}}" pd_render_onload pd_options="tickersList=true">
    </div>
    
    <div class="form-group col-sm-10" id="target{{prefix}}" pd_render_onload pd_options="tickersContent=true">
    </div>
</div>
"""

a = StockViewer()
a.run(runInDialog='false')