1.
LinkedIn에 올라온 글을 읽다가 우연히 한 논문을 보았습니다. 공동 저자를 보니까 이정현(Jeong-Hyun Lee)이라는 한국이름이 보이더군요. New York University의 Courant Institute of Mathematical Sciences에 재직하는 듯 합니다. 공동 저자인 Marco Avellaneda도 경력이 화려합니다.
He has also held positions as vice-president in the Morgan Stanley Derivative Products Group, portfolio manager in equity volatility Strategies at Gargoyle Strategic Investments LLC, Head of Volatility Arbitrage at Capital Fund Management and Portfolio Manager in quantitative equity strategies at the Galleon Group in New York. He is known as the inventor of the Uncertain Volatility model and for his work on the Weighted Monte Carlo algorithm and the theory of Dispersion Trading, as well as for several other papers in quantitative finance and derivatives. Marco has extensive experience in the fields of derivatives, quantitative strategies in equities and volatility trading from the point of view of hedge funds and Wall Street firms.
위키페이다를 보니까 ‘A well documented empirical study which confirms that StatArb profitability dropped after 2002 and 2003’라고 평가를 해놓았습니다.
이정현씨는 대한수학회 수리과학정보센터에 또다른 논문도 기고한 적이 있네요.
Generalized Brownian motions with application to finance
Machine Learning in Statistical Arbitrage라는 논문을 보면 인용논문중 하나로 나옵니다.
2.
Numerical Method라는 중국계 회사가 있습니다. 이 회사가 중국대학에 조성현씨가 했던 알고리즘트레이딩전략개발교육과 비슷한 과정을 개설해 운영하고 있습니다.
Introduction to Algorithmic Trading Strategies
2011년 Nanyang Technological University이 개설한 과정에 참여했던 Seow Kian Ping, Parambill Koyachamveettil Manu Chad, Fang Zhi Heng, Cher Zhong Ming등이 ‘Statistical Arbitrage in the U.S. Equities Market’을 실제로 구현하는 프로젝트를 진행하였습니다. 그리고 결과물을 발표했습니다.
Statistical Arbitrage in the U.S. Equities Market Presentation
Statistical Arbitrage in the U.S. Equities Market report
Statistical Arbitrage in the U.S. Equities Market code
이중 개발소스중 PCA와 관련한 부분입니다. 이런 소개를 하는 이유는 국내외 논문을 읽고 분석,구현하는 훈련을 하는 것이 퀀트 트레이더에게 필요하다는 생각이기때문입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
function main_ETF() close all;clear all % Read the ETF, stock and date information % ETF.mat contains the etf data in structured format % StockInfo.mat contains the stock data in structured format tic fprintf('============================================================\n') fprintf('PARAMETERS OPTIMIZATION\n') fprintf('------------------------------------------------------------\n') fprintf('Performing optimization...skipped! (This will take one day)\n') fprintf('------------------------------------------------------------\n') %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Optimization %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if 0 load('ETF.mat'); load('Stocks.mat'); % Select date in YYYYMMDD StartDate = 20060104; EndDate = 20081231; % Number of Stocks and ETF used NoOfStock = length(Stocks); NoOfETF = length(ETF); % Sort the desired data for selected date from ETF and stock. for ii = 1:NoOfETF ETFused(ii).name = ETF(ii).name; ETFused(ii).Return = ETF(ii).Return(find(ETF(ii).Date==StartDate):find(ETF(ii).Date==EndDate)); ETFused(ii).Date = ETF(ii).Date(find(ETF(ii).Date==StartDate):find(ETF(ii).Date==EndDate)); end for ii = 1:NoOfStock Stocksused(ii).name = Stocks(ii).name; Stocksused(ii).Return = Stocks(ii).Return(find(Stocks(ii).Date==StartDate):find(Stocks(ii).Date==EndDate)); Stocksused(ii).Date = Stocks(ii).Date(find(Stocks(ii).Date==StartDate):find(Stocks(ii).Date==EndDate)); end % Find the optimal stock for the trading strategy with the optimise score % levels. TradingParameters = []; profit = []; ProfitAll = []; Signal = []; Wealth = []; for ii = 1:NoOfStock [profit,SSO,SSC,SBO,SBC,Sigtmp,wealthtmp,stocktmp,indretur] = optimizeOmegaETF(ETFused,Stocksused,ii); TradingParameters = [TradingParameters;[SSO,SSC,SBO,SBC]]; ProfitAll = [ProfitAll;profit]; % This is the omega for Optimise omega code. Wealth = [Wealth;wealthtmp]; Signal = [Signal;Sigtmp]; save('ETFresultsOptimizeOmega.mat','TradingParameters','ProfitAll','Wealth','Signal'); end [maxProfit maxStockind] = max(ProfitAll); fprintf('==============================================\n') fprintf('The optimal stock chosen is %s with a profit of $%.2f\n',StocksUsed(maxStockind).name,maxProfit); fprintf('==============================================\n') end %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Outsample Test %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if 1 clear all load('ETF.mat'); load('Stocks.mat'); % This is the results from optimization load('ETFresultsOptimizeOmega.mat') % Select date in YYYYMMDD StartDate = 20090102; EndDate = 20101231; % Number of Stocks and ETF used NoOfStock = length(Stocks); NoOfETF = length(ETF); ETFused = []; Stocksused = []; ProfitAll(33) = 0; fprintf('============================================================\n') fprintf('BACKTESTING\n') fprintf('------------------------------------------------------------\n') fprintf('Performing Outsample test...') % Sort the desired data for selected date from ETF and stock. for ii = 1:NoOfETF ETFused(ii).name = ETF(ii).name; ETFused(ii).Return = ETF(ii).Return(find(ETF(ii).Date==StartDate):find(ETF(ii).Date==EndDate)); ETFused(ii).Date = ETF(ii).Date(find(ETF(ii).Date==StartDate):find(ETF(ii).Date==EndDate)); end for ii = 1:NoOfStock Stocksused(ii).name = Stocks(ii).name; Stocksused(ii).Return = Stocks(ii).Return(find(Stocks(ii).Date==StartDate):find(Stocks(ii).Date==EndDate)); Stocksused(ii).Date = Stocks(ii).Date(find(Stocks(ii).Date==StartDate):find(Stocks(ii).Date==EndDate)); end [maxOmega maxStockind] = max(ProfitAll); OptTradingPara = TradingParameters(maxStockind,:); OptWealth = Wealth(maxStockind,:); [TradeSignalBackTest,WealthBackTest,OmegaBackTest] = outSampleTest(ETFused,Stocksused,maxStockind,OptTradingPara); figure(1115);plot(WealthBackTest,'linewidth',2) title(sprintf('Outsample Test: P&L of %s over a 3 years period (2008-2010) with omega of %.2f for ETF','ATI',1.15),'fontsize',12) ylabel('Capital $','fontsize',12) xlabel('Time (Days)','fontsize',12) set(gca,'linewidth',2) set(gca,'fontsize',10) grid on fprintf('Completed!~\n') fprintf('------------------------------------------------------------\n') end %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% BootStrapping %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if 1 clear all; load('ETF.mat'); load('Stocks.mat'); % This is the results from optimization load('ETFresultsOptimizeOmega.mat') % Number of Monte Carlo MonteCarloRuns = 50; % Select date in YYYYMMDD StartDate = 20060104; EndDate = 20101231; % Number of Stocks and ETF used NoOfStock = length(Stocks); NoOfETF = length(ETF); ETFused = []; Stocksused = []; % Number of Bootstrapping samples SampleNo = 500; ProfitAll(33) = 0; % Optimal parameter to use [maxOmega maxStockind] = max(ProfitAll); OptTradingPara = TradingParameters(maxStockind,:); OptWealth = Wealth(maxStockind,:); TradeSignalBS = []; WealthBS = []; OmegaBS = []; fprintf('Performing Bootstrapping - 50 Monte Carlos runs...') for ii = 1:MonteCarloRuns fprintf('%d...',ii); % Bootstrapping to select SampleNo randomly from population [ETFused,Stocksused]=SampleBootstrap(ETF,Stocks,SampleNo,NoOfStock,NoOfETF); [TradeSignalBackTest,WealthBackTest,OmegaBackTest] = outSampleTest(ETFused,Stocksused,maxStockind,OptTradingPara); TradeSignalBS = [TradeSignalBS;TradeSignalBackTest]; WealthBS = [WealthBS;WealthBackTest]; OmegaBS = [OmegaBS;OmegaBackTest]; if ~isempty(find(ii == [3:13:MonteCarloRuns])) fprintf('\n') end end a = toc; fprintf('Completed Bootstrapping!\n') fprintf('Total time elapsed --> %.2f\n',a) fprintf('============================================================\n') figure(888);plot(WealthBS.') title(sprintf('50 Monte Carlo runs for Stock ATI using ETF approach (Bootstrapping)'),'fontsize',12) ylabel('Capital $','fontsize',12) xlabel('Time (Days)','fontsize',12) set(gca,'linewidth',1.2) set(gca,'fontsize',10) grid on figure(889);plot(OmegaBS,'linewidth',3) title(sprintf('Omega Stock ATI using ETF approach with mean of 1.0485 (Bootstrapping)'),'fontsize',12) ylabel('Omega','fontsize',12) xlabel('No. of Monte Carlo Runs','fontsize',12) set(gca,'linewidth',1.2) set(gca,'fontsize',10) grid on end PlotProfit function [Sigtmp,wealthtmp1,OmegaRatios] = outSampleTest(ETFData,StockData,StockInd,OptTradingPara) SSO = OptTradingPara(1); SSC = OptTradingPara(2); SBO = OptTradingPara(3); SBC = OptTradingPara(4); Sbo = SBO; Sso = SSO; Sbc = SBC; Ssc = SSC; % Number of Stocks and ETF used NoOfStock = length(StockData); NoOfETF = length(ETFData); %Optmization starts here NoOfTradingDays = length(StockData(1).Date); StockPortfolio = 0; lastTransactionDay = 0; %stores the index of the last day when stock was bought or sold ETFBetas = zeros(NoOfETF,1); %Define the initial set of betas as Zeros. wealthtmp1 = []; Sigtmp = []; PortfolioReturn = ones(NoOfTradingDays,1); %Optimzation w.r.t Omega for getting the best set of boundary values for the given stock Wealth = 1e6; StockPortfolio = 0; ETFReturn = 1; PortfolioReturn = ones(NoOfTradingDays,1); for i = 61:NoOfTradingDays IndexReturn(i) = 0; %Calculate the ETF Return for the current position for k=1:NoOfETF IndexReturn(i) = IndexReturn(i)+ ETFData(k).Return(i)*ETFBetas(k); end stockReturn = 1; IndexRet = 1; stockReturn = stockReturn * (1+StockData(StockInd).Return(i)); IndexRet = IndexRet*(IndexReturn(i)+1); %Mark to market if a there is an exposure if(StockPortfolio == 1) Wealth = Wealth*(1-IndexRet+stockReturn); elseif(StockPortfolio == -1) Wealth = Wealth*(1+IndexRet-stockReturn); end %This function call need to be MODIFIED according to the interface [Signal, Betas,ssssssss] = ETFregression(ETFData, StockData(StockInd).Return, i, Sbo, Sso, Sbc, Ssc, StockPortfolio); if(Signal == 1) if (StockPortfolio == -1) StockPortfolio = 0; %Update PandL for transaction cost Wealth = Wealth*(1-.0005); elseif(StockPortfolio == 0) % Go Long StockPortfolio = 1; ETFBetas = Betas; %Update PandL for transaction cost Wealth = Wealth*(1-.0005); end elseif(Signal == -1) if(StockPortfolio == 0) % Steps for Going Short StockPortfolio = -1; ETFBetas = Betas; %Update PandL for transaction cost Wealth = Wealth*(1-.0005); elseif(StockPortfolio == 1) StockPortfolio = 0; %Update PandL for transaction cost Wealth = Wealth*(1-.0005); end end wealthtmp1 = [wealthtmp1,Wealth]; Sigtmp = [Sigtmp,Signal]; end %Portfolio return on each day PortfolioReturn = wealthtmp1(2:end)./wealthtmp1(1:end-1)-1; %Get the PandL and Omega for the corresponding strategy %Omega calculation iAbove = 0; iBelow = 0; iAboveMeanCount = 0; iBelowMeanCount = 0; for i=1:size(wealthtmp1,2)-1 if(PortfolioReturn(i) > 0) iAbove = iAbove + PortfolioReturn(i); iAboveMeanCount = iAboveMeanCount + 1; elseif(PortfolioReturn(i) < 0) iBelow = iBelow - PortfolioReturn(i); iBelowMeanCount = iBelowMeanCount + 1; end end OmegaRatios = ((iAbove/iAboveMeanCount)*(iAboveMeanCount/(iAboveMeanCount+iBelowMeanCount)))/((iBelow/iBelowMeanCount)*(iBelowMeanCount/(iAboveMeanCount+iBelowMeanCount))); %Profit and Loss update PandL = Wealth - 1e6; function [ETFused,Stocksused] = SampleBootstrap(ETF,Stocks,SampleNo,NoOfStock,NoOfETF) a = 1; b = length(Stocks(1).Return); sampleInd = round(a + (b-a).*rand(SampleNo,1)); for ii = 1:NoOfETF ETFused(ii).name = ETF(ii).name; ETFused(ii).Return = ETF(ii).Return(sampleInd); ETFused(ii).Date = ETF(ii).Date(sampleInd); end for ii = 1:NoOfStock Stocksused(ii).name = Stocks(ii).name; Stocksused(ii).Return = Stocks(ii).Return(sampleInd); Stocksused(ii).Date = Stocks(ii).Date(sampleInd); end |