Quant Figure

QuantFigure() allows you to persist data, setting and technical analysis calculations.

It is still based on the same principles as Cufflinks:

  • Binding Plotly and Pandas for quick and efficient charting
  • Data vendor agnostic
  • Entirely Python based

Imports

In [1]:
import cufflinks as cf
import pandas as pd
import eikon as ek

Setting the Eikon App ID

In [94]:
ek.set_app_id('AD2833F918E18C4FC866')
Warning: file .portInUse was not found. Is Eikon Scripting Proxy running?
Defaulting to port 36036

Get Data

We will retrieve 7 years of daily data for

  • USD/GBP GBP FX Rate (Cable)
  • VIX VIX Volatility Index
  • SPX SPX Equity Index
  • AAPL.O Apple Inc.
In [5]:
gbp=ek.get_timeseries('gbp=',fields='*',start_date='2010-01-01',interval='weekly')
vix=ek.get_timeseries('.vix',fields='*',start_date='2010-01-01',interval='weekly')
spx=ek.get_timeseries('.spx',fields='*',start_date='2010-01-01',interval='weekly')
aapl=ek.get_timeseries('aapl.o',fields='*',start_date='2015-01-01')
In [95]:
aapl.head()
Out[95]:
AAPL.O HIGH CLOSE LOW OPEN COUNT VOLUME
Date
2015-01-02 111.44 109.33 107.350 111.39 287735.0 53204626.0
2015-01-05 108.65 106.25 105.410 108.29 318491.0 64285491.0
2015-01-06 107.43 106.26 104.630 106.54 364769.0 65797116.0
2015-01-07 108.20 107.75 106.695 107.20 222954.0 40105934.0
2015-01-08 112.15 111.89 108.700 109.23 305171.0 59364547.0

Quant Figure

We create a new QuantFigure with the GBP data.

In [96]:
qf=cf.QuantFig(gbp,title='USD/GBP',legend='top',name='GBP=')

Below you can see that the structure of the QuantFigure is aligned with the properties/metadata of a Financial chart.

In [97]:
qf
{
    "_d": {
        "close": "CLOSE", 
        "high": "HIGH", 
        "low": "LOW", 
        "open": "OPEN"
    }, 
    "data": {
        "kind": "candlestick", 
        "name": "GBP=", 
        "showlegend": true
    }, 
    "kwargs": {}, 
    "layout": {
        "annotations": {
            "params": {}, 
            "values": []
        }, 
        "legend": "top", 
        "margin": {
            "b": 40, 
            "l": 40, 
            "r": 40, 
            "t": 40
        }, 
        "rangeselector": {
            "visible": false
        }, 
        "rangeslider": false, 
        "shapes": {}, 
        "showlegend": true, 
        "title": "USD/GBP"
    }, 
    "panels": {
        "bottom_margin": 0, 
        "min_panel_size": 0.15, 
        "spacing": 0.08, 
        "top_margin": 0.9
    }, 
    "studies": {}, 
    "theme": {
        "down_color": "grey", 
        "theme": "white", 
        "up_color": "java"
    }, 
    "trendlines": []
}
Out[97]:

Plotting our first QuantFigure

In [98]:
qf.iplot()

Below we can see the structure of this Figure. The values are similar to those interpretted by cufflinks rather than

In [99]:
qf
{
    "_d": {
        "close": "CLOSE", 
        "high": "HIGH", 
        "low": "LOW", 
        "open": "OPEN"
    }, 
    "data": {
        "kind": "candlestick", 
        "name": "GBP=", 
        "showlegend": true
    }, 
    "kwargs": {}, 
    "layout": {
        "annotations": {
            "params": {}, 
            "values": []
        }, 
        "legend": "top", 
        "margin": {
            "b": 40, 
            "l": 40, 
            "r": 40, 
            "t": 40
        }, 
        "rangeselector": {
            "visible": false
        }, 
        "rangeslider": false, 
        "shapes": {}, 
        "showlegend": true, 
        "title": "USD/GBP"
    }, 
    "panels": {
        "bottom_margin": 0, 
        "min_panel_size": 0.15, 
        "spacing": 0.08, 
        "top_margin": 0.9
    }, 
    "studies": {}, 
    "theme": {
        "down_color": "grey", 
        "theme": "white", 
        "up_color": "java"
    }, 
    "trendlines": []
}
Out[99]:

All values can be overriden on the fly - without affecting the original instance.

In [100]:
qf.iplot(theme='ggplot',up_color='white',down_color='blue',title='OHLC Chart',
         showlegend=False,kind='ohlc')

Going back to our original chart - all settings are preserved

In [101]:
qf.iplot()

Aleternatively we could also change an attribute of the figure (serlalized) to make it a permanent change

In [102]:
qf.theme.update(up_color='green')
qf.iplot()

Adding a Range Selector

A rangeselector allows us to select different periods on the same chart. This can be any variety of Year, Months, Hours etc.

For example: steps=['1y','2 months','5 weeks','ytd','2mtd']

In [103]:
rangeselector=dict(steps=['Reset','3Y','2Y','1Y','YTD','6M'],
                                    bgcolor=('lime',.2),
                                    fontsize=12,fontfamily='monospace')
qf.layout.update(rangeselector=rangeselector)
In [104]:
qf.iplot()

What is going on with Cable?

Adding annotations and trendlines

In [105]:
qf.layout['annotations']['values']=[]
qf.add_annotations({'2016-06-24':'BREXIT',
                    '2016-10-07':'Flash Crash'},
                   arrowhead=6,arrowcolor='green',fontcolor='red',textangle=0)

We will add a support line to indicate where the price has struggled to break (downwards). A support line is a horizontal line. We only need the date as reference.

In [106]:
qf.add_support('2010-03-26',width=2,color='purple')

Cable Chart with Annotations

In [107]:
qf.iplot()

Adding a support line

In [108]:
qf.add_support('2016-07-08',width=2,color='purple',mode='toend')

Crossing the support line

In [109]:
qf.iplot()

Breaking the resistance?

In [110]:
qf.iplot(shapes=dict(kind='rect',x0='2017-03-31',x1='2017-04-28',y0=1.2,y1=1.35,
                    color='magenta',fillcolor='magenta',opacity=0.2))

VIX - Volatility Index

In [111]:
qf=cf.QuantFig(vix,title='VIX',legend='top',datalegend=False)
In [112]:
qf.iplot()

Resistance and Support Levels

In [113]:
qf.iplot(hspan=dict(y0=11.5,y1=16,color='mustard',fill=True,opacity=.3,yref='y2'),
         rangeslider=True)

Moving on to SPX

Adding a rangeselector

A rangeselector allows us to select change the amount of data displayed on the chart.

In [114]:
rangeselector=dict(steps=['Reset','3Y','2Y','1Y','YTD','6M'],
                                    bgcolor=('rgb(150, 200, 250)',.1),
                                    fontsize=12,fontfamily='monospace')

qf=cf.QuantFig(spx,legend='top',datalegend=False,name='SPX',rangeselector=rangeselector)

SPX with Rangeselector

In [115]:
qf.iplot()

Technical Studies

Relative Strength Indicator

In [116]:
qf.add_rsi()
In [117]:
qf.iplot()
In [118]:
qf.trendlines=[]
qf.add_trendline('07Oct11','06Feb15',on='low',text='SPX Long Term<br>Uptrend',color='purple',
                 width=2,dash='solid',ay=50,arrowhead=7,arrowcolor='green')
qf.add_trendline('06Feb15','28Apr17',on='low',y1=2600,width=2,dash='dash')
In [119]:
qf.iplot()
In [146]:
qf.add_shapes(shapes=dict(kind='rect',x0='2014-10-17',x1='2016-07-01',y0=1600,y1=2300,
                          color='grey',fill=True,opacity=.2))
qf.add_annotations(dict(x='2015-10-10',y=1600,text='Head & Shoulders<br>Pattern',
                        arrowhead=7,arrowcolor='green',ay=50))
In [147]:
qf.iplot()

We can see how the trendlines are always added as metadata

In [148]:
qf.trendlines
Out[148]:
[]
In [149]:
qf.add_shapes(vspan=dict(x0='2017-01-27',x1='2017-04-28',color='orange',fill=True,opacity=.1))
qf.add_annotations(dict(x='2017-01-27',y=70,text='RSI<br>Overbought',
                        arrowhead=7,arrowcolor='green',yref='y3',yanchor='middle',ay=30))
In [150]:
qf.iplot()

Analyzing Apple

In [151]:
qf=cf.QuantFig(aapl,legend='top',name='Apple')
In [152]:
rangeselector=dict(steps=['Reset','2Y','1Y','6M','3M','2MTD'],
                                    bgcolor=('rgb(150, 200, 250)',.1),
                                    fontsize=12,fontfamily='monospace')
qf.layout.update(rangeselector=rangeselector)
In [153]:
qf.iplot()
In [154]:
qf.add_volume(colorchange=True)
In [155]:
qf.iplot(legend='top')
In [156]:
qf.add_sma([21,55,144],colors=['green','orange','blue'],width=1)
In [157]:
qf.iplot()
In [158]:
qf.studies['sma']['display'].update(legendgroup=True)
qf.data.update(showlegend=False)
In [159]:
qf.iplot()
In [160]:
qf.add_bollinger_bands(periods=20,boll_std=2,colors=['magenta','grey'],fill=True)
In [161]:
qf.iplot()
In [162]:
qf.add_rsi(periods=20,rsi_upper=70,rsi_lower=30)
In [163]:
qf.iplot()
In [164]:
qf._get_study_figure('rsi').iplot()

Panels control how multipe charts (studies) are displayed

In [165]:
qf.panels
Out[165]:
{'bottom_margin': 0,
 'min_panel_size': 0.15,
 'spacing': 0.08,
 'top_margin': 0.9}

We can change the spacing between panels on the fly

In [166]:
qf.iplot(spacing=.05,theme='ggplot')
In [167]:
qf.add_macd(fast_period=12, slow_period=26, signal_period=9)
In [168]:
qf.iplot(spacing=.05)
In [169]:
qf.theme.update(theme='solar')
In [170]:
qf.iplot()