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!

Contact Form Powered By : XYZScripts.com