Quantitative Analysis, Risk Management, Modelling, Algo Trading, and Big Data Analysis

# Trend Identification for FX Traders (Part 2)

In my previous post I provided an introduction to the trading model invention and design. We made use of FX data of AUDUSD pair sampled hourly and splitting data into weekly time-series.

Today, we will work a bit harder over formulation of the very first rules for the model. This step will require an engagement of our creativity in understanding what data are like as well as how we can make a basic set of rules which would help us to perform an attractive time-series classification. Our objective is to invent a method which will be helpful in classification of last week FX pair’s time-series to be either in the downtrend or in the uptrend.

The most naive way of classification of directional information contained in any time-series is its slope: a straight line fit to the data. Let’s use it as our starting point. Instead of fitting all data points for a given week, we find median values for the first and the last 12 data points both in Time $(x1,x2)$ and Pair Ratio $(y1,y2)$ as specified in lines 92 to 94:

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 % FX time-series analysis % (c) Quant at Risk, 2012 % % Part 2: Classification of weekly time-series   close all; scrsz = get(0,'ScreenSize'); h=figure('Position',[70 scrsz(4)/2 scrsz(3)/1.1 scrsz(4)/2],'Toolbar','none'); fprintf('\nuptrend/downtrend identification.. '); % for viewing use the loop hold off; set(0,'CurrentFigure',h);   % pre-define variables trend=zeros(nw,1); slope=zeros(nw,1); midp={}; % middle points endp={}; % end points (median based on last 12 points)   for i=1:nw %--- a loop over total number of weeks available   % reading time-series for a current week w=week{i}; x=w(:,1); y=w(:,2);   % plot the time-series hold on; plot(x,y,'k');   % linear trend estimation x1=median(x(1:12)); x2=median(x(end-11:end)); y1=median(y(1:12)); y2=median(y(end-11:end));   % define end-point of the time-series and mark it on the plot endp{i}=[x2 y2]; hold on; plot(endp{i}(1),endp{i}(2),'b*');   % find slope m=(y2-y1)/(x2-x1); slope(i)=m; xl=x1:dt:x2; yl=m*xl-m*x2+y2; % a line of representing the slope hold on; plot(xl,yl,'b:');   % find middle point of the line and mark it on the plot mx=mean(xl); my=mean(yl); midp{i}=[mx my]; hold on; plot(midp{i}(1),midp{i}(2),'bo');

As an example of the code execution, for the first two weeks we plot slopes, mid-points and end-points:

We assume that our classification procedure will be based solely on the information provided for end-points and slopes. The exception we make for the classification of the first two weeks. For the first week the distinction between uptrend and downtrend is made based on the position of the first and last point:

113 114 115 116 117 118 119 120 121 122 123 124 % Time-Series Classification   if(i==1) ybeg=y(1); yend=y(end); if(ybeg<yend) trend(i)=+1; % uptrend hold on; plot(x,y,'k'); else trend(i)=-1; % downtrend hold on; plot(x,y,'r'); end end

where we mark the result of classification with a sign $+1$ or $-1$ in a vector element of $trend$, and plot it with black and red color denoting uptrend and downtrend, respectively.

For the second week, our rules of classification are enriched by additional information about the end-point of a current and a previous week:

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 if(i==2) % week(current-1) tmp=week{i-1}; x1=tmp(:,1); y1=tmp(:,2); y1b=y1(1); y1e=y1(end); % week(current) y0b=y(1); y0e=y(end); if(y0e>y1e) trend(i)=+1; % uptrend hold on; plot(x,y,'k'); else trend(i)=-1; % downtrend hold on; plot(x,y,'r'); end end

For weeks number 3 and higher we do our creative research over the data to define a specific set of rules. We allow to take into account the information from two weeks prior to the current one and combine them all together. The following code represents an attractive solution, subject to improvement:

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 if(i>2) % week(current-2) mid2=midp{i-2}(2); end2=endp{i-2}(2); slp2=slope(i-2); % week(current-1) mid1=midp{i-1}(2); end1=endp{i-1}(2); slp1=slope(i-1); % week(current) mid0=midp{i}(2); end0=endp{i}(2); slp0=slope(i); if((mid0>mid1)) % up-trend if((mid0>mid2)&&(end0>end1)) trend(i)=+1; hold on; plot(x,y,'k'); % strong up-trend elseif((mid0>mid2)&&(end0>end2)) trend(i)=+1; hold on; plot(x,y,'k'); % weak up-trend elseif((mid0<mid2)&&(end0<end2)&&(slp0<0)) trend(i)=-1; hold on; plot(x,y,'r'); % turns into possible down-trend elseif((mid0<mid2)&&(end0<end2)&&(slp0>0)) trend(i)=+1; hold on; plot(x,y,'k'); % turns into possible up-trend else trend(i)=+1; hold on; plot(x,y,'k'); % turns into possible up-trend end elseif(mid0<mid1) % down-trend if((mid0<mid2)&&(end0<end1)&&(end0<end2)) trend(i)=-1; hold on; plot(x,y,'r'); % weak down-trend elseif((mid0<mid2)&&(end0<end2)&&(end0>end1)) trend(i)=+1; hold on; plot(x,y,'k'); % possible up-trend elseif((mid0<mid2)&&(end0>end2)) trend(i)=+1; hold on; plot(x,y,'k'); % turns into possible up-trend elseif((mid0>mid2)&&(end0<end1)&&(end0<end2)) trend(i)=-1; hold on; plot(x,y,'r'); elseif((mid0>mid2)&&(end0>end2)) trend(i)=+1; hold on; plot(x,y,'k'); % turns into possible up-trend elseif((mid0>mid2)&&(end0>end1)) trend(i)=+1; hold on; plot(x,y,'k'); % turns into possible up-trend else trend(i)=-1; hold on; plot(x,y,'r'); end end end end

Since one picture is worth millions of lines of code, below we present three examples of our model in action. The last plot corresponds to the latest Global Financial Crisis and shows how weeks in uptrends of 2009 followed these in downtrend a year before.

It is straightforward to note that the performance of our rules works very intuitively and stays in general agreement with the market sentiments.

• GiorgioG

Hi Pawel,

I enjoyed your post so much that I challenged myself to find an alternative solution approach.
I attack it from the persepective of the most simple and pragmatic definition of trends:

>> uptrend: series of higher highs and higher lows
>> downtrend: series of lower highs and lower lows
>> neutral trend: none of the above

Hence I developed a MATLAB routine working on a self generated price chart St,
where I first identify the series of St local-max and St local-min as:

if (St(i) > St(i-1) && St(i+1) <local max at time= found>

if (St(i) St(i)) -> <local min at time= found>

This allows to compute two matrixes lmax[] and lmin[] defined as:

lmax = [time, St local max value]

lmin = [time, St local min value]

Then I plot both St and its local max and local min in figure #1.

Second step purpose is to identify trends, as classified within the {uptrend,downtrend,neutral} set.
That is based on their abovementioned definition, hence:

if (lmax(i,2) > lmax(i-1,2) && lmin(i,2) > lmin(i-1,2)) => uptrend

if (lmax(i,2) < lmax(i-1,2) && lmin(i,2) downtrend

else neutral trend

The computed trend is stored inside the matrix trend[] defined as:

trend = [trend starting time, trend value]

Then figure#2 shows the figure#1 St price chart with highlighted trends in blue/red/black colors.
I enclose herein below the MATLAB code. I would also have enclosed some results samples as jpg, however it appeared to me not possible as posted comment.

clear; clc; % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % preliminary generation of a stock price weekly chart % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% mu=0.05; % drift sigma=0.15; % std dev over total inverval S1=1; % initial capital (\$) N=100; % number of time steps (trading weeks in a year) K=1; % number of simulations dt = sigma/sqrt(N); % local volatility t=0; W=0;St=[S1];% initial boundary conditions for i=2:N eps=randn; dW = sigma*eps*sqrt(dt); S = S1*exp((mu*t-0.5*sigma*sigma*t) + W); St=[St; S]; % current time and W updated t = t + dt; % current time W = W + dW; % W(t) end % %%%%%%%%%%%%%% % trend analysis % %%%%%%%%%%%%%% % % step-1: determining local max and local min matrixes % % initial values for current min, current max, local max matrix[t,lmax], local min matrix [t,lmin] cmin=St(1);cmax=cmin;lmax=[];lmin=[]; % finding the local max and local min smax = 0; smin = 0; for i=2:1:(N-1) if (St(i) &gt; St(i-1) &amp;&amp; St(i+1) &lt; St(i)) lmax = [lmax;i,St(i);]; smax = smax + 1; cmax = St(i); end if (St(i) St(i)) lmin = [lmin;i,St(i);]; smin = smin + 1; cmin = St(i); end end % plotting stock price and highlighting above computed local max and local min hold on; figure(1); plot(St); xlim([1 N]); xlabel('Trading Weeks') ylabel('Stock Price'); title('Historical Price Chart with local max-min'); for i=1:smax plot(lmax(i,1),lmax(i,2), ':db'); end for i=1:smin plot(lmin(i,1),lmin(i,2), ':*r'); end   % % step-2: determining upper/neutral/down trends based on their pragmatic definition: % uptrend := higher highs &amp;&amp; higher lows % downtrend := lower highs &amp;&amp; lower lows % neutral trend := none of the above % % trend is a matrix whose cell is [,] % at time t=1, trend is 0 (neutral) trend = [1,0]; % +1 is uptrend; -1 is downtrend; 0 is neutral trend. s = smax; if(smin tr) tr = lmin(ct,1); end % trend computation if (lmax(i,2) &gt; lmax(i-1,2) &amp;&amp; lmin(i,2) &gt; lmin(i-1,2)) trend = [trend; tr,1;]; ct = ct + 1; elseif (lmax(i,2) &lt; lmax(i-1,2) &amp;&amp; lmin(i,2) trend(ct,1) &amp;&amp; ct 1 &amp;&amp; trend(ct-1,2) == 1) plot(x1,y1,'b'); elseif (ct &gt; 1 &amp;&amp; trend(ct-1,2) == -1) plot(x1,y1,'r'); else plot(x1,y1,'k'); end end

• Felice

Very interesting post. I’m using MatLab for testing of strategies, and your blog is very useful for me.
I have noticed that the links for 2012 posts do not work.
Thank you for sharing your knowledge.

• Pawel

Felice, thank you for your warm words. I plan to drop more code in Matlab and programming some cool strategies. Stay tuned!