import pandas_datareader as web
import pandas as pd
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
import matplotlib.pyplot as plt
from talib import abstract
import numpy as np
# download stock history data
#df = web.DataReader(name='0050.TW', data_source='yahoo', start='2014-07-25', end='2022-07-25')
#df.to_csv("stock_0050_2014_2022_0725.csv")
# build data from csv and select target data
df = pd.read_csv('stock_0050_2014_2022_0725.csv')
df = df.interpolate() #flll empty data
date_sel = df['Date']>='2014-07-25' #select target data
df_sel = df[date_sel]
df_sel['Date'] = pd.to_datetime(df_sel['Date']) #convert type to datetime
df_sel = df_sel.set_index('Date') # set date as index
#calculate KD signal with talib
df_tmp = df_sel
df_tmp.rename(columns = {'High':'high', 'Low':'low','Adj Close':'close','Close':'non_adj close'}, inplace = True) #rename for talib
kd = abstract.STOCH(df_tmp)
kd.index=df_tmp.index
fnl_df = df_tmp.join(kd).dropna() #merge two data frame
fnl_df.rename(columns = {'high':'High', 'low':'Low','close':'Close'}, inplace = True) #rename column name for backtest
def I_bypass(data): # bypass data in Strategy
return data
class KDCross(Strategy):
lower_bound = 20
upper_bound = 80
def init(self):
self.k = self.I(I_bypass, self.data.slowk) #K
self.d = self.I(I_bypass, self.data.slowd) #D
def next(self):
if crossover(self.k, self.d) and self.k<self.lower_bound and self.d<self.lower_bound and not self.position: #long position
self.buy()
elif crossover(self.d, self.k) and self.k>self.upper_bound and self.d>self.upper_bound:
if self.position and self.position.is_long:
self.position.close()
#run backtest
bt = Backtest(fnl_df, KDCross, cash=10000, commission=.002)
rslt = bt.run()
print(rslt)
bt.plot()
class KDCross(Strategy):
lower_bound = 20
upper_bound = 80
sl_ratio = 99 # stop loss ratio, 99 means 1% loss
def init(self):
self.k = self.I(I_bypass, self.data.slowk) #K
self.d = self.I(I_bypass, self.data.slowd) #D
def next(self):
if crossover(self.k, self.d) and self.k<self.lower_bound and self.d<self.lower_bound and not self.position: #long position
self.buy(size=.99,sl=self.data.Close[-1]*self.sl_ratio/100)
elif crossover(self.d, self.k) and self.k>self.upper_bound and self.d>self.upper_bound:
if self.position and self.position.is_long:
self.position.close()
因此當sell 10000 put 的這個部位衝到上百倍的價格,風險指標馬上認為你賠了爆多,以剛剛0206八點50分24秒的10000的put跟9900 put價格的例子來看,縱使因為這是100點的垂直價差單,放到到期,最大虧損也就是100點,但是風險指標認定你的本金已經虧掉1090-46=1044點,遠超過可能實際會發生的最大虧損值,如果保證金本來認為風險已經控制,所以沒有留很多,這很大機會就會造成風險指標瞬間低於25%而啟動強制平倉,逼迫去花大錢用不合理的價格買天價的put來平倉。