This is a memo of a random walk by Python. I'm writing a little mathematical formula, but it's not mathematically strict, so don't be afraid.
Price $ p (n) $ at time $ n $,
Time series calculated by adding $ d (n) $ (however, $ d (n) $ is $ 1 $ or $ -1 $) to the price $ p (n-1) $ one sample before. Is called a simple random walk.
First, $ d (n) $ can be written in Python as follows:
%matplotlib inline
import numpy as np
import pandas as pd
dn = np.random.randint(2, size=1000)*2-1
If you generate a random number of 0 or 1, double it and subtract 1, you get -1 or 1. Alternatively, you can randomly select either [-1,1]
as follows.
dn = np.random.choice([-1,1], size=1000)
If you add these in order, it will be a simple random walk. Here, the initial value is $ p (0) = 100 $.
p0 = 100
swalk = np.cumsum(dn)+p0
Let's plot it in the Series class of pandas.
pd.Series(swalk).plot()
A simple random walk adds $ + 1 $ or $ -1 $ to the previous price, but if you continue to do this, the price may become negative. It is strange that the stock price will be negative, so in order to simulate the actual movement of the stock price, we will use a geometric random walk that is a slightly modified version of the simple random walk.
Geometric random walks use the logarithmic value of the price instead of the price to formulate a similar formula.
In this equation, transpose $ \ log p (n-1) $
If you take exp () on both sides,
It will be. In other words, the formula for finding $ p (n) $ from $ p (n-1) $ is
It will be. Here, $ d (n) $ is the price of the previous sample because it can be approximated as $ e ^ \ {d (n) } \ approx 1 + d (n) $ when $ d (n) $ is small. You can see that it is the rate of change from.
However, if $ d (n) $ is the rate of change, $ + 1 $ or $ -1 $ will be the rate of change of 100%, which is too large. Here, since the change of 1 yen for 100 yen is 1%, $ d (n) $ is calculated as $ 0.01 $ or $ -0.01 $. If you use the dn
obtained by the simple random walk, the initial value is also $ p (0) = 100 $.
gwalk = np.cumprod(np.exp(dn*0.01))*p0
It is OK if you multiply ʻexp (dn * 0.01) `in order like this. This is plotted as follows:
pd.Series(gwalk).plot()
Since it uses the same $ d (n) $ as the simple random walk, it looks almost the same, but the difference between changing in 1-yen units and changing in 1% units appears a little away from 100 yen. I am.
Whether it's stocks or Forex, the actual market price isn't exactly a random walk, but you can think of it as a random walk. Here, I will try to make something close to the actual market price with a random walk.
The parameter of the geometric random walk is the fluctuation rate. In the previous example, the fluctuation rate per sample was set to 1%, but in the market world, the standard deviation of the fluctuation rate on a yearly basis is expressed by the term "volatility". Below is a site that shows the actual Forex volatility.
History Volatility (Central Tanshi FX)
A volatility of 10% means that the probability that the price will fall within $ \ pm 10 $% one year later is in the normal distribution of $ \ pm 1 \ sigma $ (approximately 68%), but in reality volatility is time. It fluctuates with. There is also a random walk model that fluctuates volatility, but here we will fix the volatility. In the case of Forex, the volatility is about 10% to 20%, so this time I will set it to 15%.
Next, it cannot be the actual market price that changes at the same rate of change each time. Therefore, we will make the changing time frame finer. For example, if you execute a random walk at 1-minute intervals, you will have performed a random walk of 60 samples in 1 hour, so the fluctuation rate per hour will change each time. As the number of samples increases, the probability of fluctuation rate becomes a normal distribution, which is closer to the actual movement.
So, let's use pandas to create a one-minute index for one year.
idx = pd.date_range('2015/01/01', '2015/12/31 23:59', freq='T')
Since the FX market does not move on weekends, only the weekday part is taken out from ʻidx`.
weekidx = idx[idx.weekday<5]
Next, create $ d (n) $ that is the same size as weekidx
.
dn = np.random.randint(2, size=len(weekidx))*2-1
Volatility is a one-year volatility, so convert this to a one-minute volatility. Calculated by dividing by the square root of the total number of 1-minute bars for the number of business days in a year (260 days).
Vola = 15.0 #Volatility(%)
scale = Vola/100/np.sqrt(260*24*60)
gwalk = np.cumprod(np.exp(scale*dn))*p0
Based on this 1-minute random walk, let's make a 4-hour random walk, for example.
df = pd.Series(gwalk, index=weekidx).resample('4H').ohlc().dropna()
Use pandas's resample () method to create 4-value data. If you display only the closing price, it will be as follows.
df['close'].plot()
Here is an example of a random walk with 15% volatility. However, the random walk has a different chart each time, so I'm not sure if it fits.
Recommended Posts