Hello.

I need to start my very first post with apologies:

Although there are already multiple discussions about indicators and strategies presented in Andreas Clenow's excellent book "Stocks on the Move", I have decided to open a new topic.

My three main reasons to do so are:

- egoism - I got many ideas from the excellent discussion Rotation of 5 Momentum Stocks (like Clenow), but want to move discussion to a somewhat different direction.
- a different approach - I get Andreas' ideas somehow different than others do, including existing topics. Maybe someone is interested to follow these approaches.
- Code confusion - maybe due to the fact that I am totally noob to AmiBroker, but I got confused by multiple topics discussing the R² coefficient of determination and thus decided to do another implementation.

Let's get started.

Andreas, in "Stocks on the Move", as you'll already know, presented a strategy to somehow rotate stocks in the S&P500 universe, using a momentum indicator, he branded with his name, the "Clenow Momentum".

If you studied his website followingthetrend.com (he already has opened another one Clenow Research, but for this topic the old one is still the reference), you know that he has a very nice and positive attitude and that this branding comes with some irony.

Later - on this web site - he added an "Advanced" Clenow Momentum, because feedback by readers of the book and contributors to the website had asked for two things:

a) Make trading easier and reduce cost for the weekend/once a month/hooby trader and

b) Adjust the strategy for people, who always want to stay in the market and not use the original system's trend filter (simply S&P500 > MA(200), of course to be replaced with an index representative for the universe you trade).

Hoping to start a discussion with you guys, interested in Andreas' ideas, in this first thread I will provide two pieces of code, the results of which I have backtested with Excel calculations, other chart software, C# code and so on, so that I'm pretty sure, it works:

- The "Simple" Clenow Momentum (the original indicator)

has been provided by others before, so please take this code more educationary, because I have added a huge comment to explain why R-squared (or R²) needs to be calculated the way I am presenting here. Spoiler: When you have calculated the slope of a regression line for, lets say day 445 with a lookback period of 90 days, your existing arrays are useless when it comes to R-squared calculation and I have seen this mistake in multiple topics. You need to calculate R-squared for the 90 days ending with the current day (445) instead, thus calculating squared differences between real quotes and your prediction function as it is on day 445 and as it would have predicted quotes the 90 days ending with today.

I have done that using a loop, but let's look at the code:

```
function ClenowMomentum(Days, outMomentum, outAnnSlope, outRsquared)
{
Tage = Days;
SetBarsRequired(Tage);
x = cm = annSlopePct = rSquared = BarIndex();
xSq = x^2;
y = Ln(Close);
xAvg = MA(x, Tage);
xSqAvg = MA(xSq, Tage);
yAvg = MA(y, Tage);
xy = x * y;
xyAvg = MA(xy, Tage);
xAvgSq = xAvg^2;
xDiff = xSqAvg - xAvgSq;
xDiff = IIf(xDiff==0, Null, xDiff);
k = (xyAvg - yAvg * xAvg) / xDiff;
annSlopePct = 100 * (EXP(250 * k) - 1);
// test: predicts = yAvg + k * (x - xAvg);
// produces exactly the same results as using buitlin LinearReg function: predicts2 = LinearReg(y, Tage);
// NOTE: The coefficient of determination, R² is defined (according to https://en.wikipedia.org/wiki/Coefficient_of_determination) as
// R² = 1 - SUM(residual squares) / SUM(total squares)
// Where, if p is the predicted value for y, residual[i] = p[i]-y[i] and totalSquare[i] = y[i]-yAvg
// The problem is, we cannot use previously calculated arrays here, because on each particular day (where we want to calcculate R²),
// we have another value for k and thus another function that has predicted the recent (Tage) values.
// Instead of using yesterdays values for k, predicts, residuals, etc, on each day, we need to calculate both sums for the recent Tage days.
// In other words: For each day we get a new linear regression of log(C), using past Tage days and need to calculate this regression's R²
// by comparing past Tage days to todays "prediction" function.
// We acheive this by initializing the two sum's arrays with today values and then use a loop to step back Tage days, adding daily values:
sumTotalSquares = (y - yAvg)^2;
sumResidualSquares = (y - yAvg - k * (x - xAvg))^2; // remember: predict[i] = yAvg + k * (x[i] - xAvg) => y[i] - predict[i] = y[i] - yAvg - k * (x[i] -xAvg)
for (lookback = -1; lookback >= 1 - Tage; lookback--)
{
deltaTotal = (Ref(y, lookback) - yAvg)^2;
deltaResidual = (Ref(y, lookback) - yAvg - k * (Ref(x, lookback) - xAvg))^2;
sumTotalSquares += deltaTotal;
sumResidualSquares += deltaResidual;
}
rSq = 1 - sumResidualSquares / sumTotalSquares;
cm = annSlopePct * rSq;
// }
VarSet(outMomentum, cm);
VarSet(outAnnSlope, annSlopePct);
VarSet(outRsquared, rSq);
return;
}
```

I have not added Plot commands here, because I want to have several functions in an include file and I am not yet experienced in branching on Status("action") to do multiple tasks in the same file. If you want to test/debug, you could simply do that:

```
cm = as = rs = 0;
d=90;
ClenowMomentum(d, "cm", "as", "rs");
printf("cm = %g\n", cm );
printf("as = %g\n", as );
printf("rs = %g\n", rs );
```

- The "Advanced" Clenow Momentum

The "Advanced" Momentum is simply an average of two "Simple" (or "Original") Momentum indicators with different lookbacks. In the models presented and backtested on his website, Andreas uses 125 and 250 days, because he figured out that these longer lookback worked out better than the original 90 days.

The systems (he presents two, using 25 and 50 stocks) the use this combined Momentum for ranking, very similar to the original system, while the trend filter is disregarded and could be replaced by a rule like "don't buy a stock when its advanced momentum is below <whatever you like, e.g. 20>, even if its high-ranked".

The calculation is simple; I have added another function using the first one from above, adding the feature of allowing you to use a weight (of first momentum) different from the original 0.5 (maybe a good Optimize candidate):

```
function ClenowAdvancedMomentum(Days1, Days2, weight1, outAdvancedClenowMomentum, outClenowMomentum1, outAnnualSlope1, outRsquared1, outClenowMomentum2, outAnnualSlope2, outRsquared2)
{
SetBarsRequired(Max(Days1, Days2));
cm1 = cm2 = as1 = as2 = rs1 = rs2 = 0;
ClenowMomentum(Days1, "cm1", "as1", "rs1");
ClenowMomentum(Days2, "cm2", "as2", "rs2");
am = cm1 * weight1 + cm2 * (1 - weight1);
VarSet(outAdvancedClenowMomentum, am);
VarSet(outClenowMomentum1, cm1);
VarSet(outAdvancedClenowMomentum, am);
VarSet(outAdvancedClenowMomentum, am);
return;
}
```

Testing:

```
am = cm1 = cm2 = as1 = as2 = rs1 = rs2 = 0;
d1 = 125;
d2 = 250;
w = 0.5;
ClenowAdvancedMomentum(d1, d2, w, "am", "cm1", "as1", "rs1", "cm2", "as2", "rs2");
printf("am = %g\n", am );
printf("cm1 = %g\n", cm1 );
printf("as1 = %g\n", as1 );
printf("rs1 = %g\n", rs1 );
printf("cm2 = %g\n", cm2 );
printf("as2 = %g\n", as2 );
printf("rs2 = %g\n", rs2 );
```

If you are a newbie as I am, the following hint might help:

In debugging, add a breakpoint to one of the print lines and then add watches to one or many of the variables am, cm1, etc.

You can then use "Arrays" pane of the debugger to inspect the whole timeline.

I hope, you find this useful.

In following posts I would love to discuss your ideas as well as Andreas suggestions when it comes to position sizing; he published multiple articles about this topic as well, but I have not yet managed to code these ideas in AmiBroker.

Promise: If we could do this together and people will forgive me stupid questions about custom backtesting I will surely raise in the near future, I will disclose everything I develop until we have built all variations of Andreas' ideas into a backtestable and hopefully tradable and profitable system.

Cheers

Christian