bookloveru2
pythonで株価分析⑫【コピペで3秒。MACDでバックテスト】
更新日:2021年11月1日
今回は、大人気シリーズ「pythonで株価分析してみた」の第12弾です❕
表題の通り、
『コピペで3秒。』で自作のMACDバックテストできます('ω')ノ
『有名な指標だけど、MACDって儲かるの❓』という疑問に答えます。
ポチるだけで、バックテストの結果が表示されます!(^^)!
今回も、コピペで行ける様、しっかりとpythonコードの解説をしていきますので、グーグルコラボのご準備をお願い致します。
では、早速行ってみましょう!(^^)!
目次
❶コピペ用pythonコードと使い方
❷一括コード
❶コピペ用pythonコードと使い方
まずは必要なライブラリを準備!(^^)!
!pip install mplfinance
import mplfinance as mpf
import datetime
import fix_yahoo_finance as yf
import matplotlib.pyplot as plt
import requests
import argparse
import numpy as np
import seaborn as sns
次は分析開始日と銘柄、任意の移動平均線を設定!(^^)!
次の5項目を入力して下さい。
start:開始日
stock:銘柄(ここではテスラ)
MA1:任意の移動平均線(ここでは5日)
MA2:任意の移動平均線(ここでは25日)
MA3:任意の移動平均線(ここでは60日)
start = "2021-1-1" #@param {type:"string"}
stock = "TSLA" #@param {type:"string"}
MA1 = 5 #@param {type:"number"}
MA2 = 25#@param {type:"number"}
MA3 = 60#@param {type:"number"}
df = yf.download(stock, start=start, end=datetime.date.today())
mpf.plot(df,type='candle',mav=(MA1,MA2,MA3),volume=True,show_nontrading=True)
ここまでの結果です👇
じゃん(*‘ω‘ *)❕
自作のチャートが出来上がりました!(^^)!
今回は今年の初めから現在までのテスラモーターズの株価推移をプロットしました!!

続いて、お待ちかねのMACDバックテストです👇
#simple moving average
def macd(signals):
signals['ma1']=signals['Close'].rolling(window=ma1,min_periods=1,center=False).mean()
signals['ma2']=signals['Close'].rolling(window=ma2,min_periods=1,center=False).mean()
return signals
#signal generation
#when the short moving average is larger than long moving average, we long and hold
#when the short moving average is smaller than long moving average, we clear positions
#the logic behind this is that the momentum has more impact on short moving average
#we can subtract short moving average from long moving average
#the difference between is sometimes positive, it sometimes becomes negative
#thats why it is named as moving average converge/diverge oscillator
def signal_generation(df,method):
signals=method(df)
signals['positions']=0
#positions becomes and stays one once the short moving average is above long moving average
signals['positions'][ma1:]=np.where(signals['ma1'][ma1:]>=signals['ma2'][ma1:],1,0)
#as positions only imply the holding
#we take the difference to generate real trade signal
signals['signals']=signals['positions'].diff()
#oscillator is the difference between two moving average
#when it is positive, we long, vice versa
signals['oscillator']=signals['ma1']-signals['ma2']
return signals
#plotting the backtesting result
def plot(new, ticker):
#the first plot is the actual close price with long/short positions
fig=plt.figure()
ax=fig.add_subplot(111)
new['Close'].plot(label=ticker)
ax.plot(new.loc[new['signals']==1].index,new['Close'][new['signals']==1],label='LONG',lw=0,marker='^',c='g')
ax.plot(new.loc[new['signals']==-1].index,new['Close'][new['signals']==-1],label='SHORT',lw=0,marker='v',c='r')
plt.legend(loc='best')
plt.grid(True)
plt.title('Positions')
plt.show()
#the second plot is long/short moving average with oscillator
#note that i use bar chart for oscillator
fig=plt.figure()
cx=fig.add_subplot(211)
new['oscillator'].plot(kind='bar',color='r')
plt.legend(loc='best')
plt.grid(True)
plt.xticks([])
plt.xlabel('')
plt.title('MACD Oscillator')
bx=fig.add_subplot(212)
new['ma1'].plot(label='ma1')
new['ma2'].plot(label='ma2',linestyle=':')
plt.legend(loc='best')
plt.grid(True)
plt.show()
def main():
#input the long moving average and short moving average period
#for the classic MACD, it is 12 and 26
#once a upon a time you got six trading days in a week
#so it is two week moving average versus one month moving average
#for now, the ideal choice would be 10 and 21
global ma1,ma2,stdate,eddate,ticker,slicer
#macd is easy and effective
#there is just one issue
#entry signal is always late
#watch out for downward EMA spirals!
ma1=int(input('ma1:'))
ma2=int(input('ma2:'))
stdate=input('start date in format yyyy-mm-dd:')
eddate=input('end date in format yyyy-mm-dd:')
ticker=input('ticker:')
#slicing the downloaded dataset
#if the dataset is too large, backtesting plot would look messy
#you get too many markers cluster together
slicer=int(input('slicing:'))
#downloading data
df=yf.download(ticker,start=stdate,end=eddate)
new=signal_generation(df,macd)
new=new[slicer:]
plot(new, ticker)
if __name__ == '__main__'
かなり長いコードでやんした(*‘ω‘ *)
結果です👇
このコードは実行後に開始日や銘柄の入力を要望してきます。
次の6項目を入力して下さい。
ma1:任意の移動平均線(ここでは5日)
ma2:任意の移動平均線(ここでは25日)
start date:開始日
end date:終了日
ticker:銘柄
slicing:データの分割数(15くらいで良いと思います)



見事にバックテストの結果が出ました(*ノωノ)
今回の例で言うと、【2月の中旬にショート。4月上旬にロング(決済)で見事に利確❕】。その後5月上旬に再度ショートにインしています(・ω・)ノ
MACD上ではテスラは、まだ売りだ!
と言っていますね。
如何でしたでしょうか?(`・ω・´)ゞ
なかなか良いぜ❕と思ってくれた方は、下記のアドレスまでビットコインの少額寄付をお願いします。($・・)/~~~
Bitcoin address
1BnvzhckxyjTLUzCaH3v5S4E6QSzPvxWkA

❷一括コード
!pip install mplfinance
import mplfinance as mpf
import datetime
import fix_yahoo_finance as yf
import matplotlib.pyplot as plt
import requests
import argparse
import numpy as np
import seaborn as sns
start = "2021-1-1" #@param {type:"string"}
stock = "TSLA" #@param {type:"string"}
MA1 = 5 #@param {type:"number"}
MA2 = 25#@param {type:"number"}
MA3 = 60#@param {type:"number"}
df = yf.download(stock, start=start, end=datetime.date.today())
mpf.plot(df,type='candle',mav=(MA1,MA2,MA3),volume=True,show_nontrading=True)
#simple moving average
def macd(signals):
signals['ma1']=signals['Close'].rolling(window=ma1,min_periods=1,center=False).mean()
signals['ma2']=signals['Close'].rolling(window=ma2,min_periods=1,center=False).mean()
return signals
#signal generation
#when the short moving average is larger than long moving average, we long and hold
#when the short moving average is smaller than long moving average, we clear positions
#the logic behind this is that the momentum has more impact on short moving average
#we can subtract short moving average from long moving average
#the difference between is sometimes positive, it sometimes becomes negative
#thats why it is named as moving average converge/diverge oscillator
def signal_generation(df,method):
signals=method(df)
signals['positions']=0
#positions becomes and stays one once the short moving average is above long moving average
signals['positions'][ma1:]=np.where(signals['ma1'][ma1:]>=signals['ma2'][ma1:],1,0)
#as positions only imply the holding
#we take the difference to generate real trade signal
signals['signals']=signals['positions'].diff()
#oscillator is the difference between two moving average
#when it is positive, we long, vice versa
signals['oscillator']=signals['ma1']-signals['ma2']
return signals
#plotting the backtesting result
def plot(new, ticker):
#the first plot is the actual close price with long/short positions
fig=plt.figure()
ax=fig.add_subplot(111)
new['Close'].plot(label=ticker)
ax.plot(new.loc[new['signals']==1].index,new['Close'][new['signals']==1],label='LONG',lw=0,marker='^',c='g')
ax.plot(new.loc[new['signals']==-1].index,new['Close'][new['signals']==-1],label='SHORT',lw=0,marker='v',c='r')
plt.legend(loc='best')
plt.grid(True)
plt.title('Positions')
plt.show()
#the second plot is long/short moving average with oscillator
#note that i use bar chart for oscillator
fig=plt.figure()
cx=fig.add_subplot(211)
new['oscillator'].plot(kind='bar',color='r')
plt.legend(loc='best')
plt.grid(True)
plt.xticks([])
plt.xlabel('')
plt.title('MACD Oscillator')
bx=fig.add_subplot(212)
new['ma1'].plot(label='ma1')
new['ma2'].plot(label='ma2',linestyle=':')
plt.legend(loc='best')
plt.grid(True)
plt.show()
def main():
#input the long moving average and short moving average period
#for the classic MACD, it is 12 and 26
#once a upon a time you got six trading days in a week
#so it is two week moving average versus one month moving average
#for now, the ideal choice would be 10 and 21
global ma1,ma2,stdate,eddate,ticker,slicer
#macd is easy and effective
#there is just one issue
#entry signal is always late
#watch out for downward EMA spirals!
ma1=int(input('ma1:'))
ma2=int(input('ma2:'))
stdate=input('start date in format yyyy-mm-dd:')
eddate=input('end date in format yyyy-mm-dd:')
ticker=input('ticker:')
#slicing the downloaded dataset
#if the dataset is too large, backtesting plot would look messy
#you get too many markers cluster together
slicer=int(input('slicing:'))
#downloading data
df=yf.download(ticker,start=stdate,end=eddate)
new=signal_generation(df,macd)
new=new[slicer:]
plot(new, ticker)
if __name__ == '__main__':
main()
では。ばいちゃ(・ω・)ノ
pythonでプログラミングがしたい!!
pythonを学びたい!という方には、
オンラインプログラミング教室『Aidemy アイデミー』がお勧めです。
ご自身でプログラム環境を用意する必要は無く、サイトへアクセスするだけです。 創業者は東京大学工学部卒の石川聡彦さん。
著書に『人工知能プログラミングのための数学がわかる本』(KADOKAWA/2018年)など。
無料で、お試しもできますので安心です。
お時間ある方は下記リンクを覗いてみてはいかがでしょうか(*'ω'*)。