# 【Quant(1)】- Backtesting

## * What is Backtesting and how to do it?

`Assumption：As long as the company's ROE exceeds 15%, then we buy it's stock, rebalance once a year, and sell when its ROE falls below 15%.`

## * 0050.TW dollar-cost averaging(DCA) method backtesting

`import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport matplotlib.ticker as tickerimport matplotlib.transforms as transformsimport datetimeimport tejapitejapi.ApiConfig.api_key = "your key"`
`TW0050 = tejapi.get(        'TWN/EWPRCD',         coid = '0050',        mdate={'gte':'2016-01-01', 'lte':'2020-12-31'},         opts={'columns': ['mdate','close_adj']},         paginate=True        )TW0050['mdate'] = TW0050.loc[:,'mdate'].astype('datetime64[ns]')TW0050 = TW0050.set_index('mdate')##change the frequency of the dataTW0050_monthly = TW0050.resample('MS').first()##add the last day of our historical data           TW0050_monthly = TW0050_monthly.append(TW0050.iloc[-1])TW0050_monthly`
`##Shares to buy in each month(chop off)TW0050_monthly['每月購買股數']=    np.floor(10000 /　TW0050_monthly['close_adj'])TW0050_monthly['每月購買股數'][-1] = 0##Cumulative SharesTW0050_monthly['累積股數'] = TW0050_monthly['每月購買股數'].cumsum()##Cumulative Shares ValueTW0050_monthly['累積價值(月)'] = 　　round(TW0050_monthly['累積股數'] * TW0050_monthly['close_adj'],2)##Original Asset ValueTW0050_monthly['原始價值(月)'] = 　　[10000*i for i in range(len(TW0050_monthly.index))]TW0050_monthly['原始價值(月)'] = 　　TW0050_monthly['原始價值(月)'].shift(-1)TW0050_monthly['原始價值(月)'][-1] = TW0050_monthly['原始價值(月)'][-2]##Cumulative ReturnTW0050_monthly['累積報酬(月)'] = 　　round((TW0050_monthly['累積價值(月)']-TW0050_monthly['原始價值(月)'])/TW0050_monthly['原始價值(月)'], 6) +1`
`plt.figure(figsize = (10, 6))plt.plot(TW0050_monthly['累積價值(月)'], lw=1.5, label = '0050')plt.plot(TW0050_monthly['原始價值(月)'], lw=1.5, label = 'Original Asset')plt.xlabel('Time(Year)')plt.ylabel('Value')plt.legend(loc = 0) plt.grid()    `
`##Monthly returnret = 　　np.log(TW0050_monthly['累積報酬(月)']/TW0050_monthly['累積報酬(月)'].shift(1))fig, ax = plt.subplots()ret.plot(kind="bar", figsize=(12,6), stacked=True, ax=ax)##Build an empty array with the length of total dataticklabels = ['']*len(TW0050_monthly.index)##Show the month and the date every 6 monthsticklabels[::6] = 　　[item.strftime('%b %d') for item in TW0050_monthly.index[::6]]##Show the year every 12 monthsticklabels[::12] = 　　[item.strftime('%b %d\n%Y') for item in TW0050_monthly.index[::12]]ax.xaxis.set_major_formatter(ticker.FixedFormatter(ticklabels))plt.gcf().autofmt_xdate()##Add the horizontal line of average monthly returnax.axhline(ret.mean(), c='r')plt.xlabel('Month')plt.ylabel('Return')plt.title('0050 Monthly return')plt.show()`
`##CAGRcagr = (TW0050_monthly['累積報酬(月)'][-1]) ** (1/5) -1##Annually Standard Deviationstd = ret.std()*np.sqrt(12)##Sharpe Ratio(Assume that Rf is 1%)shapre_ratio = (cagr-0.01)/std##MDDroll_max = TW0050_monthly['累積價值(月)'].cummax()monthly_dd =TW0050_monthly['累積價值(月)']/roll_Max - 1.0max_dd = monthly_dd.cummin()##Tablepd.DataFrame(columns=['0050'], 　　index=['年化報酬率(%)', '年化標準差(%)', '夏普比率', '期間最大回撤(%)'], 　　data = np.round(np.array([100*cagr, 100*std, sharpe_ratio, 100*max_dd[-1]]),2))` 