Trading Forex: (2) Trend Identification

In my previous article on Trading Forex: (1) Trend Identification 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:

% 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:

trading forex

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:

    % 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:

    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:

    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.

trading forex

trading forex

trading forex

 

Explore Further

Trading Forex: (1) Trend Identification
Probability of a Limit Order Execution
Trading with the trend




Subscribe to QuantAtRisk Newsletter!

3 comments
  1. 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) > St(i-1) && St(i+1) < 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 && higher lows
    %         downtrend := lower highs && 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) > lmax(i-1,2) && lmin(i,2) > lmin(i-1,2))
            trend = [trend; tr,1;];
            ct = ct + 1;
        elseif (lmax(i,2) < lmax(i-1,2) && lmin(i,2)  trend(ct,1) && ct  1 && trend(ct-1,2) == 1)
            plot(x1,y1,'b');
        elseif (ct > 1 && trend(ct-1,2) == -1)
            plot(x1,y1,'r');
        else
            plot(x1,y1,'k');            
        end
    end
    

  2. 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.

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

Leave a Reply

Your email address will not be published. Required fields are marked *