Moving average trading rule - Adding filters

4 views (last 30 days)
Wildman
Wildman on 19 Aug 2015
Commented: Wildman on 26 Aug 2015
Dear all,
I'm trying to code a moving average (crossover) trading rule with some filter rules. However I get stuck with translating the theory to a Matlab code.
This rule generates a buy signal (value "1") when the fast moving average is above the slow moving average and sell signals (value "-1") vice versa. Where a slow moving average (variable "n" days) is calculated over a greater number of days than the fast moving average (variable "m" days). Same procedure goes for the case where only one (slow) moving average is taken (the case where "m=0") and the price index. The data I use are historical data (a vector of 31225x1, consisting of only index prices on trading days).
The Matlab code for the moving average crossover trading rule (without any filters), where it saves all trading signals of each rule (120 rules in total) in one variable "tr_ma" (which consists of 120 "31225x1 vectors"):
%Moving average crossovers
for n=[2 5 10 15 20 25 30 40 50 75 100 125 150 200 250];
ma_slow=tsmovavg(price,'s',n,1);
for m=[0 2 5 10 15 20 25 30 40 50 75 100 125 150 200 250];
if n<=m; continue, end
if m~=0;
ma_fast=tsmovavg(price,'s',m,1);
end
k=k+1; % Increment the counter
if m~=0;
cross=[NaN; diff(sign(ma_fast-ma_slow))]; % Compute diff of signal
elseif m==0;
cross=[NaN; diff(sign(price-ma_slow))]; % compute diff of signal
end
ix=abs(cross)==2;
cross(ix)=cross(ix)/2; % Scale transitions to +/-1
tr_ma(k)={cross}; % Store as cell
end
end
Now I'm trying to add two filters to this rule ( note: only one filter is active at the time. So you need two codes in the end, one for each filter addition):
--------------------------------------------------
1) The time delay filter (d): requires the buy or sell signal to remain valid for a prespecified number of days, d, before action is taken. d=[2 3 4 5]
The problem: The code has to put a trade only when "d" times buy or sell signals uninterrupted has been generated (so when the fast moving average is "d" times above the slow moving average, generate a buy signal after the "d" times etc.). For example if you have in row 1 till 5 the following signals and "d"=2: [0 0 -1 -1 -1], in row 5 the code has to put a trade (sell) signal and replace the "-1" in row 3 and 4 with a zero. So you get [0 0 0 0 -1].
and
2) Holding period filter (c): consider holding a given long or short position for a prespecified number of trading days (ignoring all other signals during that time), c. c=[5 10 25 50]
The problem: The code has to ignore (so give those rows the value zero) for "c" number of trading days (in my case rows) any buy or sell signals after a trade (buy/sell) has been done. And check again after "c" days if it generates a buy or sell signal etc.
--------------------------------------------------
I can't seem to get those two filters working. Adding a for-loop ("for i=1:31225" etc.) where you let the program calculate cell by cell makes it very slow and don't even works in the end. I thought about the "find" function but again I found a death end.
Does anybody have a suggestion how I can tackle those two filters?
Thanks,
Wildman
  7 Comments
dpb
dpb on 25 Aug 2015
i1=find(S,1); % first move, buy or sell (non-zero)
i2=find(S(i1+1:end)~=S(i1),1)+i1; % first change in action afterwards
If i2-i1>=C, that's one looking for, if <C then find the next starting at i2.
This is all the testing needed if, as the above shows, you've cleared all "hold" signals, otherwise you need a second test to ensure it's not 0. Oh, just dawned on me, don't use "~=S(i1)" as the test, use "==-S(i1)"; that guarantees it's the opposite sign or the other trade action.
Wildman
Wildman on 26 Aug 2015
That is actually almost the same thing what I have coded, after you gave me some fresh ideas!
Before the while loop I generated a variable "cross" with zeros for length(price), so I don't need to clear any rows/give any rows the value zero (because they are already there). After that I generated a start buy/sell signal at "t=n" and run the while loop (which takes the "filtered" signals out of the standard "index_cross" variable and put them in the "cross" variable).
The code for the filter part (the while loop):
.....
t=n;
while t<=length(price);
if cross(t,:)==1 || cross(t,:)==-1; %Check if a buy/sell signal is generated
prev_signal=cross(t,:); %Store the buy/sell signal
t=t+c-1; %Holding period of c days (including current day)
else index_1=find(index_cross(t+1:end,:)==-prev_signal,1,'first'); %Find first opposite sign
cross(t+index_1,:)=index_cross(t+index_1,:); %Store in the matrix
t=t+index_1; %Move on
end
end
.....
It seems this code does the trick!
--------------------------------------------
"Oh, just dawned on me, don't use "~=S(i1)" as the test, use "==-S(i1)"; that guarantees it's the opposite sign or the other trade action."
--------------------------------------------
Good point! I changed that part in my code, indeed it guarantees it only takes the opposite sign.
Thanks for everything, have a great day!

Sign in to comment.

Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!