Nam_Hoang_Waw

Adaptive Moving Average

Mar 2nd, 2019
268
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.33 KB | None | 0 0
  1. import pandas as pd
  2. import numpy as np
  3. import cmath as mt
  4. import pylab as pl
  5. from matplotlib import style
  6.  
  7. style.use('ggplot')
  8.  
  9. # importing training period:
  10.  
  11. df1 = np.genfromtxt('NASDAQ_training.csv',delimiter=',')
  12.  
  13. # importing testing period:
  14.  
  15. df2 = np.genfromtxt('NASDAQ_testing.csv',delimiter=',')
  16.  
  17. # converting csv file to dataframe format:
  18.  
  19. array1 = pd.DataFrame(df1)
  20. array2 = pd.DataFrame(df2)
  21.  
  22. # naming each column of the dataframe:
  23.  
  24. array1.columns = ['Index','Open','High','Low','Close','Adj Close','Volume']
  25. array2.columns = ['Index','Open','High','Low','Close','Adj Close','Volume']
  26.  
  27. # remove redundant column which contains only NaNs:
  28.  
  29. del array1['Index']
  30. del array2['Index']
  31.  
  32. # remove redundant row which contains only NaNs:
  33.  
  34. array1 = array1[1:]
  35. array2 = array2[1:]
  36.  
  37. # select only Adj.Close from the data frame:
  38.  
  39. array_adj_close1 = array1.ix[:, 'Adj Close']
  40. array_adj_close2 = array2.ix[:, 'Adj Close']
  41.  
  42. # convert the Adj.Close to ndarray format (numpy):
  43.  
  44. array_adj_close1 = array_adj_close1.values
  45. array_adj_close2 = array_adj_close2.values
  46.  
  47. # Creating a class project that calculate the return of AMA strategy
  48.  
  49. class project:
  50.  
  51.     # Constructor that's initialized with an array object:
  52.  
  53.     def __init__ (self,array,cumulative_pnl):
  54.         self.array = array
  55.         self.cumulative_pnl = cumulative_pnl
  56.  
  57.     # Creating method of calculating PnL:
  58.  
  59.     def PnL(self, ks, kf, interval, sd_interval, y):
  60.  
  61.         # Creating a matrix of 15 x (len(self.array) of zeros:
  62.  
  63.         data_matrix = np.zeros((len(self.array), 15))
  64.  
  65.         # Creating a vector of Vt:
  66.  
  67.         runningsum = 0
  68.         r = 0
  69.  
  70.         for i in range(0, len(self.array)):
  71.             if i + interval < len(self.array):
  72.                 for j in range(0, interval):
  73.                     runningsum += abs(self.array[i + interval] - self.array[i + interval - 1 - j])
  74.             else:
  75.                 break
  76.             data_matrix[r + interval][0]= runningsum
  77.             r += 1
  78.             runningsum = 0
  79.  
  80.         # Creating a vector of Dt:
  81.  
  82.         r = 0
  83.         runningsum = 0
  84.  
  85.         for i in range(0, len(self.array)):
  86.             if i + interval < len(self.array):
  87.                 runningsum += self.array[i + interval] - self.array[i]
  88.             else:
  89.                 break
  90.             data_matrix[r + interval][1] = runningsum
  91.             r += 1
  92.             runningsum = 0
  93.  
  94.         # Creating a Pt vector:
  95.  
  96.         r = 0
  97.  
  98.         for i in self.array[interval:]:
  99.             data_matrix[r+interval][3] = i
  100.             r += 1
  101.  
  102.     # Creating an ER vector:
  103.  
  104.         r = 0
  105.  
  106.         for i in range(len(self.array)-interval):
  107.             data_matrix[r + interval][4] = (data_matrix[r + interval][1] / data_matrix[r + interval][0])
  108.             r += 1
  109.  
  110.     # Creating a Ct vector:
  111.  
  112.         fastest = 2 / (kf + 1)
  113.         slowest = 2 / (ks + 1)
  114.  
  115.         r = 0
  116.  
  117.         for i in range(len(self.array)-interval):
  118.             data_matrix[r+interval][5] = ((data_matrix[r+interval][4] * (fastest - slowest) + fastest))
  119.             r += 1
  120.  
  121.         runningsum = 0
  122.  
  123.     # Creating the first moving average:
  124.  
  125.         for i in self.array[0:interval-1]:
  126.             runningsum += i
  127.  
  128.         SMA = runningsum / interval
  129.         AMA = SMA
  130.  
  131.         r = 0
  132.  
  133.     # Creating AMA array:
  134.  
  135.         for i in range(len(self.array)-interval):
  136.             AMA = AMA + data_matrix[r+interval][5] * (data_matrix[r + interval][3] - AMA)
  137.             data_matrix[r + interval][6] =  AMA
  138.             r += 1
  139.  
  140.         r = 0
  141.  
  142.     # Filter array:
  143.  
  144.         data_matrix[interval:, 7] = pd.rolling_std(data_matrix[interval:, 6], window=sd_interval)
  145.  
  146.         data_matrix[:, 7] = np.nan_to_num(data_matrix[:, 7])
  147.  
  148.         data_matrix[:, 7] = y * data_matrix[:, 7]
  149.  
  150.     # Signal array:
  151.  
  152.         # Buy when the AMA rises above a prior n-period low by an amount greater than the filter.
  153.         # Sell when the AMA falls below a prior n-period high by an amount greater than the filter.
  154.         # If the current signal does not satisfy the above conditions, it will take the precedent signal.
  155.  
  156.         for i in range(0, len(self.array) - interval - sd_interval):
  157.  
  158.             if data_matrix[i + sd_interval + interval][6] - np.amin(data_matrix[i + interval:i + sd_interval + interval - 1, 6]) > data_matrix[i + sd_interval + interval - 1][7]:
  159.                 data_matrix[i + sd_interval + interval][8] = 1
  160.             elif data_matrix[i + sd_interval + interval][6] - np.amax(data_matrix[i + interval:i + sd_interval + interval - 1, 6]) < data_matrix[i + sd_interval + interval - 1][7]:
  161.                 data_matrix[i + sd_interval + interval][8] = -1
  162.             else:
  163.                 data_matrix[i + sd_interval + interval][8] = data_matrix[i - 1 + sd_interval + interval][8]
  164.  
  165.     # PnL array:
  166.  
  167.         # PnL = signal [t] * (P[t] - P[t-1]):
  168.  
  169.         for i in range(len(self.array)-interval-sd_interval):
  170.             data_matrix[i + sd_interval + interval][9] = data_matrix[i + sd_interval + interval][8] * (data_matrix[i + sd_interval + interval][3]-data_matrix[i + sd_interval + interval - 1][3])
  171.  
  172.     # Cumulative PnL:
  173.  
  174.         runningsum = 0
  175.  
  176.         for i in range(len(self.array)-interval-sd_interval):
  177.             runningsum += data_matrix[i + sd_interval + interval][9]
  178.             data_matrix[i + sd_interval + interval][10] = runningsum
  179.  
  180.         self.cumulative_pnl = data_matrix[sd_interval + interval:, 10]
  181.         return data_matrix[len(self.array)-1][10]
  182.  
  183. # Create a a class to store the cumulative PnL at different point of time:
  184.  
  185. class buy_n_hold:
  186.  
  187.     def __init__(self,array,cumulative_pnl):
  188.         self.array = array
  189.         self.cumulative_pnl = cumulative_pnl
  190.  
  191.     def cum_pnl(self,interval, sd_interval):
  192.  
  193.         runningsum = 0
  194.  
  195.         for i in range(len(self.array) - interval - sd_interval):
  196.             runningsum += self.array[i + sd_interval + interval] - self.array[i + sd_interval + interval - 1]
  197.             self.cumulative_pnl.append(runningsum)
  198.         a = self.cumulative_pnl
  199.         return a
  200.  
  201.  
  202.  
  203. # parameters to be optimized:
  204.  
  205. ks = np.arange(1,10,1)
  206. kf = np.arange(10,100,10)
  207. interval = np.arange(5,30,5)
  208. sd_interval = np.arange(30,90,30)
  209. y = [0.15,0.20,0.25,0.30]
  210.  
  211. # Create a dataframe that contains all the parameters:
  212.  
  213. df = pd.DataFrame(index=range(0,20000),columns=['ks','kf','interval','sd_interval','y','PnL'])
  214.  
  215. # Create an object of type project:
  216.  
  217. cumulative_pnl_1 = []
  218. project_pnl_cal = project(array_adj_close1,cumulative_pnl_1)
  219.  
  220. # Storing the AMA's PnL with corresponding parameters:
  221. n = 0
  222. for i in ks:
  223.     for j in kf:
  224.         for m in interval:
  225.             for o in sd_interval:
  226.                 for p in y:
  227.                         df.ix[n,'ks'] = i
  228.                         df.ix[n,'kf'] = j
  229.                         df.ix[n,'interval'] = m
  230.                         df.ix[n, 'sd_interval'] = o
  231.                         df.ix[n, 'y'] = p
  232.                         df.ix[n,'PnL'] = project_pnl_cal.PnL(j,i,m,o,p)
  233.                         n += 1
  234.  
  235. # Displaying the 5 sets of parameters with the best results of the training period (in descending order):
  236.  
  237. result = df.sort_values(['PnL'],ascending = False)
  238.  
  239. print (result.head())
  240.  
  241. # As seen from the dataframe, the best set of parameters is:
  242.  
  243. #    ks     kf         interval     sd_interval     y           PnL
  244. #    1      10         25           30              0.3         13123.4
  245. #    1      50         25           30              0.3         13100.4
  246. #    1      80         25           30              0.3         13100.4
  247. #    1      60         25           30              0.3         13100.4
  248.  
  249. # where interval is AMA n period and sd_interval is AMA standard deviation period
  250.  
  251. # So clearly, the best set of parameters is:
  252.     # ks = 1
  253.     # kf = 10
  254.     # AMA n period (interval) = 25
  255.     # AMA standard deviation period (sd_interval) = 30
  256.     # y = 0.3
  257.  
  258. # PnL of buy and hold strategy over the training period:
  259.  
  260. #print (array_adj_close1[-1]-array_adj_close1[0])
  261.  
  262. # Create an array that stores cumulative PnL of buy and hold at different point of time:
  263.  
  264. cumulative_pnl_2 = []
  265.  
  266. buy_n_hold_pnl_cal = buy_n_hold(array_adj_close2,cumulative_pnl_2)
  267. project_pnl_cal = project(array_adj_close2,cumulative_pnl_2)
  268.  
  269. # Plot the performance of AMA strategy vs. buy and hold strategy:
  270.  
  271.     # Create 2 arrays of AMA cumulative PnL and Buy and Hold cumulative PnL that shows profit at every single point of time:
  272.  
  273. project_cumulative_pnl = project_pnl_cal.PnL(10,1,25,30,0.3)
  274. buy_n_hold_cumulative_pnl = buy_n_hold_pnl_cal.cum_pnl(25,30)
  275. project_cumulative_pnl_vec = project_pnl_cal.cumulative_pnl
  276.  
  277.     # Create index for the plot function:
  278.  
  279. index1 = np.arange(0,len(project_cumulative_pnl_vec),1)
  280. index2 = np.arange(0,len(buy_n_hold_cumulative_pnl),1)
  281.  
  282.     # Plot the cumulative PnL of both strategies:
  283.  
  284. pl.plot(index1,project_cumulative_pnl_vec,'r',label ='AMA cumulative PnL',linestyle='--')
  285. pl.plot(index2,buy_n_hold_cumulative_pnl,'b', label = 'Buy n Hold cumulative PnL')
  286. pl.legend(loc='top right')
  287. pl.show()
  288.  
  289. # Annualized return of portfolio of AMA strategy vs. portfolio of Buy and Hold strategy:
  290.  
  291. AMA_ROR = (project_cumulative_pnl_vec [-1]+array_adj_close2[-1] - project_cumulative_pnl_vec[0]-array_adj_close2[55])/(project_cumulative_pnl_vec[0]+array_adj_close2[55])*100
  292. Annualized_AMA_ROR = (1+AMA_ROR)**(365/471)
  293. print(Annualized_AMA_ROR)
  294.  
  295. Buy_n_Hold_ROR = (buy_n_hold_cumulative_pnl[-1]+array_adj_close2[-1] - buy_n_hold_cumulative_pnl[0] - array_adj_close2[55])/(buy_n_hold_cumulative_pnl[0]+array_adj_close2[55])*100
  296. Annualized_Buy_n_Hold_ROR = (1+Buy_n_Hold_ROR)**(365/471)
  297. print(Annualized_Buy_n_Hold_ROR)
  298.  
  299. # Create arrays that contain value of each portfolio at different point of time:
  300.     # portfolio_value will reflect the portfolio of AMA strategy at every single point of testing time
  301.     # buy_n_hold_value will reflect the portfolio of buy and hold strategy at every single point of testing time
  302.  
  303. portfolio_value = np.add(project_cumulative_pnl_vec[:],array_adj_close2[55:])
  304. buy_n_hold_value = np.add(buy_n_hold_cumulative_pnl[:],array_adj_close2[55:])
  305.  
  306. # Risk free rate from 2009-2015:
  307. # Source: http://www.multpl.com/10-year-treasury-rate/table/by-year
  308.  
  309. annual_Rf = [0.0252,0.0373,0.0339,0.0197,0.0191,0.0286,0.0188,0.0209]
  310.  
  311. # Convert annual risk free rate to daily risk free rate:
  312.  
  313. daily_annual_Rf = np.mean(annual_Rf)/252
  314.  
  315. # Annualized Information Ratio:
  316.  
  317. def IR(Rp,Ri):
  318.     Rp_mean = []
  319.     for i in range(0,len(Rp)):
  320.         if i+1 < len(Rp):
  321.             Rp_mean.append(mt.log(Rp[i+1]/Rp[i]))
  322.     Rp_return = np.mean(Rp_mean)
  323.  
  324.     Ri_mean = []
  325.     for i in range(0,len(Ri)):
  326.         if i+1 < len(Ri):
  327.             Ri_mean.append(mt.log(Ri[i + 1] / Ri[i]))
  328.     Ri_return = np.mean(Ri_mean)
  329.  
  330.     excess_return_std = np.std(np.subtract(Rp_mean,Ri_mean))
  331.  
  332.     return mt.sqrt(252)*(Rp_return - Ri_return)/excess_return_std
  333.  
  334. print (IR(portfolio_value,buy_n_hold_value))
  335.  
  336. # Annualized Information Ratio = 1.2
  337.  
  338. # Annualized Sharpe Ratio:
  339.  
  340. def SR(Rp,Rf):
  341.  
  342.     Rp_mean = []
  343.  
  344.     for i in range(0,len(Rp)):
  345.         if i+1 < len(Rp):
  346.             Rp_mean.append(mt.log(Rp[i+1]/Rp[i]))
  347.  
  348.     Rp_return = np.mean(Rp_mean)
  349.  
  350.     excess_return_std = np.std(np.subtract(Rp_mean,Rf))
  351.  
  352.     return mt.sqrt(252)*(Rp_return - Rf)/excess_return_std
  353.  
  354. print (SR(portfolio_value,daily_annual_Rf))
  355.  
  356. # Annualized Sharpe ratio = 2.89
Add Comment
Please, Sign In to add comment