[PYTHON] Make a currency chart that can be moved around with Plotly (2)

This is a continuation of Qiita --u1and0 / Creating a currency chart that can be moved around with Plotly (1). You can now add / delete / initialize indicators.

gif8.gif

Preparation

Module import

Import the required modules.

# ----------General Module----------
import numpy as np
import pandas as pd
# ----------User Module----------
from randomwalk import randomwalk
import stockplot as sp
# ----------Hide General Module----------
import stockstats
import plotly
conda install plotly
pip install stockstats

Creating sample data

# Make sample data
np.random.seed(10)
df = randomwalk(60 * 60 * 24 * 90, freq='S', tick=0.01, start=pd.datetime(2017, 3, 20))\
    .resample('T').ohlc() + 115  #1 minute for 90 days,Initial value is 115

Create a random exchange chart. Create a 1-minute bar from 2017/3/20 for 90 days ** with the randomwalk function.

Instantiation

# Convert DataFrame as StockPlot
fx = sp.StockPlot(df)

Instantiate with the StockPlot class.

Drawing candlesticks

Convert the timeframe once instantiated with fig = sp.StockPlot (sdf). Use the resample method when converting.

fx.resample('4H').head()
close open high low
2017-03-20 00:00:00 115.34 115.00 115.98 114.79
2017-03-20 04:00:00 116.03 115.34 116.48 115.16
2017-03-20 08:00:00 116.31 116.03 116.75 115.76
2017-03-20 12:00:00 115.92 116.32 116.87 115.62
2017-03-20 16:00:00 114.36 115.92 116.12 113.85

After setting the timeframe, try plotting.

fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png1')

png1.png

This is the review of Last article.


Manipulation of indicators

Addition of indicators

Let's plot the index. Plot the most popular Simple Moving Average. Use the ʻappend` method to add it.

fx.append('close_25_sma')
fx.stock_dataframe.head()
close open high low close_25_sma
2017-03-20 00:00:00 115.34 115.00 115.98 114.79 115.340000
2017-03-20 04:00:00 116.03 115.34 116.48 115.16 115.685000
2017-03-20 08:00:00 116.31 116.03 116.75 115.76 115.893333
2017-03-20 12:00:00 115.92 116.32 116.87 115.62 115.900000
2017-03-20 16:00:00 114.36 115.92 116.12 113.85 115.592000
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png2')

png2.png

close_25_sma (25-legged simple moving average) has been added. If you execute the ʻappend` method alone on Jupyter Notebook or Ipython, the value of close_25_sma will be displayed as the return value.

Even if the added index changes the timeframe, the value will change according to the timeframe.

fx.resample('15T')
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png3')

png3.png

After changing to 15 minutes with the resample method, close_25_sma is still added without using the ʻappend` method.

This is because the index is added to the graph when the plot method is executed, not when the ʻappend` method is executed.

The ʻappend method only stores the values in self._indicators`.

self.append()


# ========self._Store indicators in indicator==========
    def append(self, indicator):
        indicator_value = self.stock_dataframe[indicator]
        self._indicators[indicator] = indicator_value  # self._In indicators format in dictionary format
        return indicator_value

self.plot()


# =======self when executing plot method._The indicator stored in the indicator_append_Pass to graph==========
    def plot(self, (Abbreviation)):
        # (Omission)
        # ---------Append indicators----------
        for indicator in self._indicators.keys():
            self._append_graph(indicator, start_plot, end_plot)  # Re-append indicator in graph
        # (Omission)
        return self._fig

self._append_graph()


# =======self._The indicator stored in the indicator is self._Add to the data part of fig==========
    def _append_graph(self, indicator, start, end):
        graph_value = self._indicators[indicator].loc[start:end]
        plotter = go.Scatter(x=graph_value.index, y=graph_value,
                             name=indicator.upper().replace('_', ' '))  #Format conversion to add to the graph
        self._fig['data'].append(plotter)

Delete indicator

Use the pop method to delete the metric.

fx.pop('close_25_sma')
fx.stock_dataframe.head()
open high low close
2017-03-20 00:00:00 115.00 115.26 114.87 115.11
2017-03-20 00:15:00 115.11 115.21 114.85 115.01
2017-03-20 00:30:00 115.01 115.49 114.90 115.47
2017-03-20 00:45:00 115.47 115.50 115.24 115.26
2017-03-20 01:00:00 115.25 115.49 115.10 115.27
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png3_1')

png6.png

close_25_sma has been removed.

I will also draw indicators other than the simple moving average.

fx.append('close_20_ema')  #Exponential moving average of closing price
fx.append('boll')  #Bollinger band middle(close_20_Same as sma)
fx.append('boll_ub')  #On Bollinger Bands
fx.append('boll_lb')  #Under Bollinger Bands
fx.append('high_0~20_max')  #The highest value of movement 20 feet ago
fx.append('low_0~20_min')  #The lowest price to move 20 feet ago
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png4')

png4.png

Was plotted.

If you don't know the name of the index you added, you can access it from the instance variable.

fx._indicators.keys()
dict_keys(['low_0~20_min', 'boll', 'high_0~20_max', 'boll_ub', 'close_20_ema', 'boll_lb'])

ʻWhen the appendmethod is used, the argument is key and the return value is value, and it is saved in the_indicatorsin dictionary format. Therefore, you can call the index name added by thekeys` method.

You can also view it with fx.stock_dataframe.columns, but it is not recommended. stockstats.StockDataFrame also raises ancillary columns when generating metrics. Therefore, auxiliary indicators (data not plotted in the graph) are also mixed, and it is difficult to distinguish which is plotted.

fx.stock_dataframe.columns
Index(['open', 'high', 'low', 'close', 'close_20_ema', 'close_20_sma',
       'close_20_mstd', 'boll', 'boll_ub', 'boll_lb', 'high_0_s', 'high_1_s',
       'high_2_s', 'high_3_s', 'high_4_s', 'high_5_s', 'high_6_s', 'high_7_s',
       'high_8_s', 'high_9_s', 'high_10_s', 'high_11_s', 'high_12_s',
       'high_13_s', 'high_14_s', 'high_15_s', 'high_16_s', 'high_17_s',
       'high_18_s', 'high_19_s', 'high_20_s', 'high_0~20_max', 'low_0_s',
       'low_1_s', 'low_2_s', 'low_3_s', 'low_4_s', 'low_5_s', 'low_6_s',
       'low_7_s', 'low_8_s', 'low_9_s', 'low_10_s', 'low_11_s', 'low_12_s',
       'low_13_s', 'low_14_s', 'low_15_s', 'low_16_s', 'low_17_s', 'low_18_s',
       'low_19_s', 'low_20_s', 'low_0~20_min'],
      dtype='object')

When displaying the index by fx.stock_dataframe.columns, the index name that has not been added is also displayed.

Since it has been messed up, delete high_20_max and low_20_min.

fx.pop('high_0~20_max')
fx.pop('low_0~20_min')
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png5')

png5.png

Only high_20_max and low_20_min have been removed from the graph.

Follow the steps below for the pop method.

  1. Delete the value specified by indicator from self._indicator.
  2. Extract only ʻopen, high, low, close from self.stock_dataframe`.
  3. Plot the remaining indicators in self._indicators again.

self.pop()


    def pop(self, indicator):
        popper = self._indicators.pop(indicator)  # (1)
        self.stock_dataframe = reset_dataframe(self.stock_dataframe)  # (2)
        for reindicator in self._indicators.keys():
            self.stock_dataframe.get(reindicator)  # (3)
        return popper

The indicators contained in self.stock_dataframe are a mixture of auxiliary columns depending on the added indicators. Therefore, it is difficult to identify "only columns created by a certain index" and remove them from self.stock_dataframe. Therefore, once self.stock_dataframe is returned to the state where resample is applied (2), the index is added again (3).

(3) is almost the same as the ʻappend method, but it does not add to self._indicators. Since the extra indicators have not been removed from self._indicators in step (1), there is no need to add them to self._indicators` again.

Indicator initialization

Use the clear method to erase all the added indicators.

fx.clear()
fx.stock_dataframe.head()
open high low close
2017-03-20 00:00:00 115.00 115.26 114.87 115.11
2017-03-20 00:15:00 115.11 115.21 114.85 115.01
2017-03-20 00:30:00 115.01 115.49 114.90 115.47
2017-03-20 00:45:00 115.47 115.50 115.24 115.26
2017-03-20 01:00:00 115.25 115.49 115.10 115.27
fx.plot(start_view='first', end_view='last')
fx.show('png', filebasename='png6')

png6.png

self.clear()


    def clear(self, hard=False):
        self._fig = None  # <-- plotly.graph_objs
        self._indicators = {}
        if hard:
            self.stock_dataframe = None
            self.freq = None  #Foot time width
        else:
            self.stock_dataframe = reset_dataframe(self.stock_dataframe)

The clear method is almost the same as the __init __ method,

That is, there is no need to use the resample method when plotting again

Is different from __init__.

Summary and supplement

flowchart

The order of use of each method is as shown in the flowchart below.

png8.png

The left side shows Add and Show, and the right side shows Delete and Reset.

About Bollinger Bands

In stockstats, the movement interval used in Bollinger Bands and $ \ sigma $ are defined as class variables.

BOLL_PERIOD = 20
BOLL_STD_TIMES = 2

Now try changing the travel section to 5, $ \ sigma $ to 1.

sp.ss.StockDataFrame.BOLL_PERIOD = 5  #Bollinger Bands movement section setting
sp.ss.StockDataFrame.BOLL_STD_TIMES = 1  #Bollinger band σ setting
boll = sp.StockPlot(df)
boll.resample('4H')
boll.append('boll')  #Bollinger band middle(close_5_Same as sma)
boll.append('boll_ub')  #On Bollinger Bands
boll.append('boll_lb')  #Under Bollinger Bands
boll.plot(start_view='first', end_view='last')
boll.show('png', filebasename='png7')

png7.png

It's a pity that $ \ sigma_1 $ and $ \ sigma_2 $ cannot be drawn at the same time.

Since BOLL_PERIOD and BOLL_STD_TIMES are class variables of stockstats, It should be redefined as stockplot.stockstats.BOLL_STD_TIMES = 2.

However, when stockstats adds an metric, it uses the _get method, so the metric once added will be overwritten.

If you just draw it on a graph, it seems that you can do something, but it will be a future task.

About subcharts

stockstats supports the output of many indicators, but many indicators require subcharts. (MACD, RSI, ADX ...) The subcharts have not been touched in this release. When I try using Cufflinks, I feel that subplots can be easily done.

About the top gif file

The first gif image shows the chart being interactively output as html from ipython.

/bin/stockplot_quickset.py


# ----------General Module----------
import numpy as np
import pandas as pd
# ----------User Module----------
from randomwalk import randomwalk
import stockplot as sp
# ----------Plotly Module----------
import plotly.offline as pyo
pyo.init_notebook_mode(connected=True)

# Make sample data
np.random.seed(1)
#Change 1 second tick for 90 days to 1 minute
df = randomwalk(60 * 60 * 24 * 90, freq='S', tick=0.01, start=pd.datetime(2017, 3, 20)).resample('T').ohlc() + 115

# Convert StockDataFrame as StockPlot
fx = sp.StockPlot(df)

# Resample as Day OHLC
fx.resample('H')

I uploaded the source code to github. github - u1and0/stockplot

Recommended Posts

Make a currency chart that can be moved around with Plotly (2)
Make a currency chart that can be moved around with Plotly (1)
[Python] Make a graph that can be moved around with Plotly
Draw a graph that can be moved around with HoloViews and Bokeh
Let's make a diagram that can be clicked with IPython
Make a Spinbox that can be displayed in Binary with Tkinter
Make a Spinbox that can be displayed in HEX with Tkinter
How to make a rock-paper-scissors bot that can be easily moved (commentary)
Make a nice graph with plotly
I made a shuffle that can be reset (reverted) with Python
[Python] Draw elevation data on a sphere with Plotly and draw a globe that can be rotated round and round
Get a list of camera parameters that can be set with cv2.VideoCapture and make it a dictionary type
File types that can be used with Go
List packages that can be updated with pip
A memo for making a figure that can be posted to a journal with matplotlib
Moved Raspberry Pi remotely so that it can be LED attached with Python
Format DataFrame data with Pytorch into a form that can be trained with NN
I made a familiar function that can be used in statistics with Python
Convert images from FlyCapture SDK to a form that can be used with openCV
Color list that can be set with tkinter (memorial)
Python knowledge notes that can be used with AtCoder
Limits that can be analyzed at once with MeCab
Format summary of formats that can be serialized with gensim
It seems that Skeleton Tracking can be done with RealSense
NumPy zeros can be defined even with a size of 0
Create a web API that can deliver images with Django
Implement a thread that can be paused by exploiting yield
I investigated the pretreatment that can be done with PyCaret
I made a plug-in that can "Daruma-san fell" with Minecraft
Candle chart plot with plotly
Make a fortune with Python
Make a fire with kdeplot
Understand the probabilities and statistics that can be used for progress management with a python program
About the matter that torch summary can be really used when building a model with Pytorch
[Python] A program that finds the maximum number of toys that can be purchased with your money
If you know Python, you can make a web application with Django
I made a package that can compare morphological analyzers with Python
A timer (ticker) that can be used in the field (can be used anywhere)
Comparison of 4 styles that can be passed to seaborn with set_context
A memo when creating an environment that can be debugged with Lambda @ Edge for the time being
[Python] Code that can be written with brain death at the beginning when scraping as a beginner
Can I be a data scientist?
Let's make a GUI with python.
Make a sound with Jupyter notebook
Let's make a breakout with wxPython
Make a recommender system with python
requirements.txt can be commented out with #
Make a filter with a django template
Confirmation that rkhunter can be installed
Let's make a graph with python! !!
Let's make a supercomputer with xCAT
Make a model iterator with PySide
Create a BOT that can call images registered with Discord like pictograms
Technology that supports a money-throwing service that can monetize a blog with one tag
I created a template for a Python project that can be used universally
[Python] A program that finds a pair that can be divided by a specified value
Acoustic signal processing module that can be used with Python-Sounddevice ASIO [Application]
The LXC Web Panel that can operate LXC with a browser was wonderful
Make a Discord Bot that you can search for and paste images
[Can be done in 10 minutes] Create a local website quickly with Django
Mathematical optimization that can be used for free work with Python + PuLP