Trend following investment system

A trend following investment strategy buys an asset that has risen recently and sells it when it has stopped rising. A common way to define"has risen" is to see if the last price exceeds the moving average of closing prices over the last N days. An R script to test such strategies for various exchange-traded funds (ETFs) and a translation to Fortran largely done by ChatGPT o3-mini (given the R script and its output) are at

The Fortran program output is

 prices_file: prices.csv

Symbol  First_Date   Last_Date  Days
   SPY  1993-01-29  2025-03-28  8097
   EFA  2001-08-27  2025-03-28  5932
   EEM  2003-04-14  2025-03-28  5526
   EMB  2007-12-19  2025-03-28  4346
   HYG  2007-04-11  2025-03-28  4522
   LQD  2002-07-30  2025-03-28  5704

 Unconditional returns and volatility
Symbol  Ann_Ret  Ann_Vol
   SPY     9.72    18.61
   EFA     5.43    20.97
   EEM     8.10    27.26
   EMB     4.17    11.05
   HYG     4.67    11.15
   LQD     4.52     8.44

 Returns and volatility conditional on the price being above or below the moving average
Symbol  MA_Length   Ann_Ret_Above   Ann_Vol_Above  Fraction_Above   Ann_Ret_Below   Ann_Vol_Below  Fraction_Below
   SPY     100.00            8.39           13.52            0.73           13.48           28.35            0.27
   SPY     200.00           10.33           13.92            0.77            7.78           29.65            0.23
   EFA     100.00            8.13           14.78            0.65            2.05           29.08            0.35
   EFA     200.00            7.93           14.79            0.69            1.66           30.87            0.31
   EEM     100.00           10.34           20.46            0.61            1.14           35.53            0.39
   EEM     200.00            4.37           20.56            0.64            8.65           36.97            0.36
   EMB     100.00            6.05            8.48            0.66            0.38           15.13            0.34
   EMB     200.00            5.23            7.98            0.71            3.60           16.39            0.29
   HYG     100.00            5.45            7.47            0.74            3.20           17.95            0.26
   HYG     200.00            5.57            6.72            0.76            2.82           19.70            0.24
   LQD     100.00            5.31            6.28            0.68            1.95           11.89            0.32
   LQD     200.00            4.66            6.40            0.72            2.07           12.42            0.28

Looking at the lines

 Returns and volatility conditional on the price being above or below the moving average
Symbol  MA_Length   Ann_Ret_Above   Ann_Vol_Above  Fraction_Above   Ann_Ret_Below   Ann_Vol_Below  Fraction_Below
   SPY     100.00            8.39           13.52            0.73           13.48           28.35            0.27
   SPY     200.00           10.33           13.92            0.77            7.78           29.65            0.23

One sees that since 1993, U.S. annualized stock returns have been higher, 10.33% vs. 7.78%, with a much lower annualized standard deviation (volatility), 13.92% vs. 29.65%, after SPY (which tracks the S&P 500 index) has closed above rather than below its 200-day moving average. For the 100-day moving average the volatility pattern is the same, but returns are higher when the price is below the moving average. Higher stock market volatility after declines than rises has been modelled by asymmetric GARCH models, implemented in the NAG library and by me in Fortran (WIP).

The Fortran code was largely auto-generated and is not pretty. I would write a cleaner program using my dataframe type and the statistics functions in that repo. The price data can be obtained from an R script using the quantmod package.

2 Likes