66 lines
2.2 KiB
Matlab
66 lines
2.2 KiB
Matlab
clear;
|
|
|
|
% 1 minute data on GLD-USO
|
|
load('inputData_ETF', 'tday', 'syms', 'cl');
|
|
idxG=find(strcmp('GLD', syms));
|
|
idxU=find(strcmp('USO', syms));
|
|
|
|
x=cl(:, idxG);
|
|
y=cl(:, idxU);
|
|
|
|
lookback=20; % Lookback set arbitrarily short
|
|
hedgeRatio=NaN(size(x, 1), 1);
|
|
for t=lookback:size(hedgeRatio, 1)
|
|
regression_result=ols(y(t-lookback+1:t), [x(t-lookback+1:t) ones(lookback, 1)]);
|
|
hedgeRatio(t)=regression_result.beta(1);
|
|
end
|
|
|
|
y2=[x y];
|
|
|
|
yport=sum([-hedgeRatio ones(size(hedgeRatio))].*y2, 2); % The net market value of the portfolio is same as the "spread"
|
|
hedgeRatio(1:lookback)=[]; % Removed because hedge ratio is indterminate
|
|
yport(1:lookback)=[];
|
|
y2(1:lookback, :)=[];
|
|
|
|
% Bollinger band strategy
|
|
entryZscore=1;
|
|
exitZscore=0;
|
|
|
|
MA=movingAvg(yport, lookback);
|
|
MSTD=movingStd(yport, lookback);
|
|
zScore=(yport-MA)./MSTD;
|
|
|
|
longsEntry=zScore < -entryZscore; % a long position means we should buy EWC
|
|
longsExit=zScore > -exitZscore;
|
|
|
|
shortsEntry=zScore > entryZscore;
|
|
shortsExit=zScore < exitZscore;
|
|
|
|
numUnitsLong=NaN(length(yport), 1);
|
|
numUnitsShort=NaN(length(yport), 1);
|
|
|
|
numUnitsLong(1)=0;
|
|
numUnitsLong(longsEntry)=1;
|
|
numUnitsLong(longsExit)=0;
|
|
numUnitsLong=fillMissingData(numUnitsLong); % fillMissingData can be downloaded from epchan.com/book2. It simply carry forward an existing position from previous day if today's positio is an indeterminate NaN.
|
|
|
|
numUnitsShort(1)=0;
|
|
numUnitsShort(shortsEntry)=-1;
|
|
numUnitsShort(shortsExit)=0;
|
|
numUnitsShort=fillMissingData(numUnitsShort);
|
|
|
|
numUnits=numUnitsLong+numUnitsShort;
|
|
positions=repmat(numUnits, [1 size(y2, 2)]).*[-hedgeRatio ones(size(hedgeRatio))].*y2; % [hedgeRatio -ones(size(hedgeRatio))] is the shares allocation, [hedgeRatio -ones(size(hedgeRatio))].*y2 is the dollar capital allocation, while positions is the dollar capital in each ETF.
|
|
pnl=sum(lag(positions, 1).*(y2-lag(y2, 1))./lag(y2, 1), 2); % daily P&L of the strategy
|
|
ret=pnl./sum(abs(lag(positions, 1)), 2); % return is P&L divided by gross market value of portfolio
|
|
ret(isnan(ret))=0;
|
|
|
|
figure;
|
|
plot(cumprod(1+ret)-1); % Cumulative compounded return
|
|
|
|
fprintf(1, 'APR=%f Sharpe=%f\n', prod(1+ret).^(252/length(ret))-1, sqrt(252)*mean(ret)/std(ret));
|
|
% APR=0.178249 Sharpe=0.964673
|
|
|
|
% Save this for future use
|
|
% save('bollinger', 'hedgeRatio', 'MA', 'MSTD');
|