Hi, Shrewd!        Login  
Shrewd'm.com 
A merry & shrewd investing community
Best Of BRK.A | Best Of | Favourites & Replies | All Boards | Post of the Week!
Search BRK.A
Shrewd'm.com Merry shrewd investors
Best Of BRK.A | Best Of | Favourites & Replies | All Boards | Post of the Week!
Search BRK.A


Stocks A to Z / Stocks B / Berkshire Hathaway (BRK.A)
Unthreaded | Threaded | Whole Thread (12) |
Post New
Author: lizgdal   😊 😞
Number: of 3957 
Subject: G-score backtest
Date: 11/09/2024 5:05 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 15
G-score is a metric developed about 20 years ago to rank growth stocks, with one point given for 8 measures. I made a gtr1 screen based on Mohanram's G-score, and get similar results: stocks with higher G-scores had higher returns. Results from 19880302 to 20241107 for the screen {GscoreHigh_dv50p}:

  Gscore   CAGR  GSD  count
HIGH(6,7) 13 22 126
LOW(0,1) -3 32 40
HIGH-LOW 16


G-score is only calculated for the lowest 20% of Book-to-Market stocks. I calculated a new field [GAscore] that has no Book value criteria. This increases the number of passing stocks, with similar results:

 GAscore   CAGR  GSD  count
HIGH(6,7) 14 19 427
LOW(0,1) 3 28 183
HIGH-LOW 11


Combining GAscore with 5-year sales growth has good CAGR, but also high GSD.
Define {GAscoreSG}
step0: [Security Type] == 11
step1: [Mkt Days Since Security Opened] >= 63
step2: [Average dollar-volume over 63 days] > 0
step3: [Average dollar-volume over 63 days] Top 50%
step4: [SalesY1] > 0
step5: [SalesY6] > 0
step6: [GAscore] == 7
step7: [[SalesY1]/[SalesY6]] Top 10; Cash When Fewer
Holding period = 21 mkt days, 0.4% friction

Results from 19880302 to 20241107:
      Screen       CAGR  GSD  MDD  Sharpe  Beta  AT
GAscoreSG 17 33 -61 0.59 1.3 3
SP1500EqualWeight 12 21 -60 0.54 1.1 0


===================
Details:
Mohanram backtested G-score from 1979 to 1999. From the abstract: "This paper tests whether a strategy based on financial statement analysis of low book-to-market (growth) stocks is successful in differentiating between winners and losers in terms of future stock performance. I create an index (G_SCORE) based on a combination of traditional fundamentals such as earnings and cash flows and measures appropriate for growth firms such as the stability of earnings and growth and the intensity of R&D, capital expenditure and advertising. A strategy based on buying high G_SCORE firms and shorting low G_SCORE firms consistently earns significant excess returns... The stock market in general and analysts in particular are much more likely to be positively surprised by firms whose growth oriented fundamentals are strong, indicating that the stock market fails to grasp the future implications of current fundamentals." (See Mohanram's 2005 paper "Separating Winners from Losers among Low Book-to-Market Stocks using Financial Statement Analysis".)

G-score has 8 parts, with one point given for each:
G1: Return on Assets (ROA) exceeding the industry median.
G2: Cash flow ROA exceeding the industry median.
G3: Cash flow from operations exceeding net income.
G4: Earnings variability (measured by the variance of ROA over the past five years) being less than the industry median.
G5: Sales growth variability (variance over the past five years) being less than the industry median.
G6: R&D intensity (R&D expenditure as a percentage of total assets) exceeding the industry median.
G7: Capital expenditure intensity exceeding the industry median.
G8: Advertising intensity exceeding the industry median.

Mohanram used the 2-digit SIC code as the industry. Medians were calculated using the lowest 20% of Book-to-Market stocks (including stocks with negative equity). Mohanram did not deblank the fields, but assigned 0 to the variability measures if less than three years of information was available. All firms with price and book value information were included. Returns for 1 year and 2 year holds were calculated from 1979 to 1999, with a 21% CAGR difference between HIGH and LOW G-score stocks.

  G-score    count  pct   MeanReturnY1  firm-years
ALL 994 100% 8.2% 20866
HIGH(6,7,8) 109 11% 17.4% 2290
LOW(0,1) 157 16% -4.0% 3295
HIGH-LOW 21.4%


G-score has many calculation steps, and so I separated the task into 2 parts: calculate G-scores, and then screen stocks. The gtr1 field [Gscore] is calculated uses SIP industry codes, and does not include G8.
step0 to step6: deblanking steps.
step7: Book-to-Market bottom 20%.
step8: calculate industry medians and [Gscore].

The gtr1 screen {GscoreHigh} imports the field [Gscore]
step0: Gscore = 6 or 7
(253 mkt days Holding period, 0.4% Friction)

Results from 19880302 to 19991231 (count is the average count of stocks passing the screen) are similar to Mohanram's results, with a 22% CAGR difference between HIGH and LOW Gscore stocks. (The time periods are different: Mohanram's backtest was 21 years ending in 1999, this {GscoreHigh} backtest was 12 years ending in 1999.)

  Gscore   count  pct   CAGR  GSD
>=0 1215 100% 9.4 22
HIGH(6,7) 170 14% 20.0 19
LOW(0,1) 169 14% -1.9 26
HIGH-LOW 21.9


Results, with 24 years post-discovery, from 19880302 to 20241107 continue to show higher CAGR for higher Gscore:
  Gscore   count  pct   CAGR  GSD
>=0 1053 100% 6.0 27
HIGH(6,7) 154 15% 13.4 22
LOW(0,1) 134 13% -4.1 32
HIGH-LOW 17.5



The screen {GscoreHigh_dv50p} uses the same [Gscore] calculation, but adds liquidity criteria to the screening stage.
import [Gscore] calculated using all stocks.
step0: no ETFs, CEFS, or LPs.
step 1 to step3: dollar volume top 50%
step 4: Gscore = 6 or 7
step 5: recent 10Q report.
step 6: no recent mergers.
(253 mkt days Holding period, 0.4% Friction)

Results from 19880302 to 20241107 continue to show higher CAGR for higher Gscore:
  Gscore   count  pct   CAGR  GSD
>=0 579 100% 8.3 26
HIGH(6,7) 126 22% 12.8 22
LOW(0,1) 40 7% -3.2 32
HIGH-LOW 16.0


G-score is only calculated for the lowest 20% of Book-to-Market stocks. I calculated a new field [GAscore] that has no Book value criteria. ([GAscore] calculates industry medians using all stocks. In contrast, [Gscore] calculates industry medians using only Book-to-Market bottom 20% stocks.)
Results from 19880302 to 20241107 show higher CAGR for higher GAscore:
 GAscore   count  pct   CAGR  GSD
>=0 2387 100% 10.4 23
HIGH(6,7) 427 18% 13.6 19
LOW(0,1) 183 8% 2.6 28
HIGH-LOW 10.9


links to screens:

{GscoreHigh}
https://gtr1.net/2013/?!!QlpoMTFBWSZTWX0CUwoAB7Dfg...

{GscoreHigh_dv50p}
https://gtr1.net/2013/?!!QlpoMTFBWSZTWaewUKoACDXfg...

{GAscoreHigh_dv50p}
https://gtr1.net/2013/?!!QlpoMTFBWSZTWSl0!2FLUAB47...

{GAscoreSG}
https://gtr1.net/2013/?!!QlpoMTFBWSZTWciKjbcAB8jfg...
Print the post


Author: Aussi   😊 😞
Number: of 3957 
Subject: Re: G-score backtest
Date: 11/09/2024 11:21 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 0
Lizgdal

Awesome coding of GTR1!

Could you please describe this field

Create [COAInd]: [0.5*[Top 50% Cut-Off by [COA], grouped by [IndGroup], at step8] + 0.5*[Bottom 50% Cut-Off by [COA], grouped by [IndGroup], at step8]]

I think it is meant to calculate the median, but I don't understand how. If I have 5 values (1,2,3,4,5), what is the value for Top 50% and Bottom 50%? If I have 6 values (1,2,3,4,5,6) what are the values?

Thanks

Aussi
Print the post


Author: bacon   😊 😞
Number: of 3957 
Subject: Re: G-score backtest
Date: 11/10/2024 9:25 AM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 0
Results, with 24 years post-discovery, from 19880302 to 20241107 continue to show higher CAGR for higher Gscore

Impressive. What, though, are the results strictly post-discovery: 20000101 to 20241107? That would eliminate the influence of the test period.

Eric Hines
Print the post


Author: lizgdal   😊 😞
Number: of 3957 
Subject: Re: G-score backtest
Date: 11/10/2024 1:45 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 3
Some industries only have a few stocks. The average of bpcut 50% and tpcut 50% is close to the median.

=======
Example that finds median of data: 1,2,3,4,5
number of data points = N = 5

bpcut 50%
0. sort data in ascending order: 1,2,3,4,5
1. bx = (N * Bottom%/100 rounded down) = 2
2. 2nd data point is 2

tpcut 50
0. sort data in descending order: 5,4,3,2,1
1. tx = (N * Top%/100 rounded down) = 2
2. 2nd data point is 4

=========
The average of tpcut and bpcut is equal to the median when the sample size is even. Some examples with 20241107 data:

Ticker  [IndGroup]  [ROAq1]  tpcut50  bpcut50  [ROAInd]
NC 5010101 -7% 11% -1% 5%
HNRG 5010101 -1% 11% -1% 5%
BTU 5010101 9% 11% -1% 5%
ARCH 5010101 11% 11% -1% 5%
CEIX 5010101 15% 11% -1% 5%


Ticker  [IndGroup]  [ROAq1]  tpcut50  bpcut50  [ROAInd]
VET 5010201 -13% 7% 6% 6%
MG 5010201 -1% 7% 6% 6%
E 5010201 3% 7% 6% 6%
SHEL 5010201 4.7% 7.2% 5.7% 6.5%
TGS 5010201 5.7% 7.2% 5.7% 6.5%
EQNR 5010201 7.2% 7.2% 5.7% 6.5%
PBR 5010201 7.4% 7.2% 5.7% 6.5%
TTE 5010201 8% 7% 6% 6%
SU 5010201 8% 7% 6% 6%
CVE 5010201 8% 7% 6% 6%


https://gtr1.net/2013/?~checkG1:lf-1lp-1h1::Assets...
Print the post


Author: lizgdal   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/10/2024 2:23 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 2
Gscore results have been fairly consistent. Looking at a few 10-year periods, HIGH-LOW range was around 13 to 23.

                           CAGR
From To yrs HIGH-LOW
19880302 19991231 12 22 test data
19991231 20241107 25 16 post-discovery
19880302 20241107 37 18 overall

19880302 19980302 10 23 rolling 10-yr
19941104 20041105 10 20 rolling 10-yr
20041105 20141107 10 13 rolling 10-yr
20141107 20241107 10 18 rolling 10-yr


  Screen    CAGR  GSD  MDD    From       To     yrs  count
GscoreAll 6.0 27 -74 19880302 20241107 37 1053
GscoreHigh 13.4 22 -57 19880302 20241107 37 154
GscoreLow -4.1 32 -89 19880302 20241107 37 134

GscoreAll 9.4 22 -41 19880302 19991231 12 1215
GscoreHigh 20.0 19 -31 19880302 19991231 12 170
GscoreLow -1.9 26 -68 19880302 19991231 12 169

GscoreAll 4 28 -74 19991231 20241107 25 975
GscoreHigh 10 23 -57 19991231 20241107 25 146
GscoreLow -5 34 -89 19991231 20241107 25 117

GscoreAll 7 26 -50 20141107 20241107 10 854
GscoreHigh 14 21 -35 20141107 20241107 10 146
GscoreLow -3 33 -73 20141107 20241107 10 106

GscoreAll 7 24 -62 20041105 20141107 10 967
GscoreHigh 12 20 -51 20041105 20141107 10 131
GscoreLow -1 29 -72 20041105 20141107 10 109

GscoreAll 5 33 -74 19941104 20041105 10 1333
GscoreHigh 15 27 -57 19941104 20041105 10 190
GscoreLow -5 39 -84 19941104 20041105 10 170

GscoreAll 6 19 -33 19880302 19980302 10 1176
GscoreHigh 18 18 -26 19880302 19980302 10 164
GscoreLow -5 22 -57 19880302 19980302 10 164

Print the post


Author: lizgdal   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/10/2024 3:11 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 3
G-score can be summarized as:
Cash flow from operations exceeds net income.
High Return on Assets (ROA) and Cash flow ROA.
Low Earnings variability and Sales growth variability.
High R&D and Capital expenditures.

some links:

Man+Machine – The evolution of fundamental scoring models and ML implications, October 8, 2021

1968 Altman’s Z-Score: "praised at the time for a significant level of accuracy of 94% in predicting company bankruptcy one year before the event"

1996 Sloan ratio: "Sloan’s main conclusion is that earnings driven by accruals are less persistent than those low accruals."

1999 Beneish’s M-Score: "easy and quick way to spot the probability of earnings manipulation of a stock"

2014 SEC Account Quality Model: "AQM is designed to detect whether a company’s financial disclosures differ greatly from its industry peers."

2000 Piotroski’s F-Score: "main purpose is to deliver a single metric to allow investors to adopt a systematic approach to fundamental value investing... Piotroski’s model inherently favours an investment style with a clear value tilt"

2005 Mohanram’s G-Score: "with the objective of finding a systematic way of investing in growth stocks"

"A recently published study by Amor-Tapia and Tascon in 2016 tests multiple scoring models using four different European stock markets. Surprisingly, Mohanram’s G-Score and Piotroski’s F-Score were the only ones surviving an out-of-sample backtesting delivering statistically significant alpha despite the other rejected models being developed at a later date."
https://www.cfauk.org/pi-listing/man-machine-the-e...

In January 2024, yuvaltaylor posted: "I wrote about the F-Score at length here: Why Piotroski's F-Score No Longer Works. There are a number of other X-Score thingies out there. I use a modified version of Beneish’s M-Score, which I outlined here: Detecting Financial Fraud: A Close Look at the Beneish M-Score, as well as Ohlson’s O-Score and Dechow’s F-Score. There’s also Altman’s Z Score. They all have merits and problems. One problem with these scores is that they mainly rely on multilinear regression rather than weighted ranking, and that’s just not as good a method."
https://community.portfolio123.com/t/man-machine-t...

In Febuary 2020, yuvaltaylor posted: "here’s my formula for the g-score"
https://community.portfolio123.com/t/scoring-syste...
Print the post


Author: RAMc   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/11/2024 1:31 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 6
Eric: “What, though, are the results strictly post-discovery: 20000101 to 20241107?”
Just put a starting date 20000103 in lizgdal’s G-Score high GTR1 link and I got:

CAGR 11.6, GSD 20.6, UI 9.2, SAWR 9.9%

In the paper fundamental equity analysis “Man+Machine – The evolution of fundamental scoring models and ML implications”.
Evolution of Fundamental Scoring Models | CFA UK
They state:
“Despite their many weaknesses and newly developed scoring models challenging their dominance flourishing over the last two decades, both Piotroski’s F-Score and Mohanram’s G-Score have not been ditched by investors. A recently published study by Amor-Tapia and Tascon in 2016 tests multiple scoring models using four different European stock markets. Surprisingly, Mohanram’s G-Score and Piotroski’s F-Score were the only ones surviving an out-of-sample backtesting delivering statistically significant alpha despite the other rejected models being developed at a later date.”
You referenced P123’s Yuval Taylor post with his version of a G Score equation above which you can use in their ranking system or a simulation. But P123 Also has a Mohanram GScore Screen.
I just ran a Backtest using P123's GScore Screen for equities in the SP1500 from 1/3/2002.
25 stocks, 4 week rebalance, 0.25% slippage, CAGR 10.7% vs S&P 9.4% nice but not exceptional.
However almost all the outperformance came in the last 15 years.

Rerunning a rolling backtest(multiple start dates)
11/11/2014 – 11/11/2024
523 Samples, Start Frequency every Week, Holding Period 3 Months:
Scrn SP500
Annualized 20.06% 13.33%
One Month 4.46% 3.21%
Three Month 15.96% 12.58%
One Year 52.85% 39.75%
Three Year 23.57% 33.76%
Five Year 159.67% 109.17%
Total 522.85% 249.80%
Risk
Sharpe Ratio 0.91 0.74
Sortino Ratio 1.27 0.99
Max Drawdown -34.2% -33.7%
Standard Dev 19.6% 15.3%
Correlation 0.83 -
R-Squared 0.68 -
Beta 1.06 -
Alpha (annualized) 6.01%
Print the post


Author: platykurtic   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/11/2024 6:19 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 4
Nice work, especially for an Annual screen (low trading for those that are taxed)!

Just adding the standard BCC (and a small change to 252 trading days for reasons - doesn't change the results really) to (mostly) reduce the moderately frequent negative years already improves the GscoreHigh screen to ...

Results				
Statistics are calculated from 19880302 to 20241108 over daily closing portfolio values for all 252 trading cycles.

Avg Min Max SD

CAGR: 15.028172 14.20667 15.926455 0.29794
TR: 16984.583984 12976.708984 22527.361328 1629.75708
Log2TR: 7.410031 7.030856 7.821925 0.137083
SAWR(20; 0.95): 10.612482 9.939157 11.330691 0.300106
GSD(20): 18.980368 18.355295 19.567358 0.24761
DIGSD(20; 0%): 21.148109 20.386206 21.979813 0.377738
LDD(20; 0%): 11.445286 11.032278 11.952506 0.22102
LDDD3: 8.119306 7.436218 8.881767 0.268355
MDD: -38.182415 -46.089619 -33.897877 2.281894
UI(20): 11.809819 10.573466 13.663349 0.571028
Sharpe(20): 0.731354 0.683201 0.77604 0.015233
Beta(20): 0.783587 0.7678 0.801364 0.007492
TI(20): 16.158493 15.192879 17.07169 0.333716
AT: 1.107518 1.064199 1.148228

Slightly higher CAGR (+1.36pp), lower GSD (-2.93pp), circa +1.5 SAWR & lower drawdowns (-38.2 vs. -57.2) at the expense of greater AT (1.11 vs. 0.63)(but you'd mostly want to trade to cash at those times anyway). A fine starting point for a screen (perhaps needs a final sort).

https://gtr1.net/2013/?~GscoreHigh:h252f0.1::Gscor...
Print the post


Author: lizgdal   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/11/2024 8:31 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 2
Thanks for posting the P123 results for comparison.

I just ran a Backtest using P123's GScore Screen for equities in the SP1500 from 1/3/2002.
25 stocks, 4 week rebalance, 0.25% slippage, CAGR 10.7% vs S&P 9.4%


The 10.7 CAGR is slightly lower than the gtr1 results:

           screen             CAGR  SDcg  depth    from       to     P123          notes
GAscore_top25_SP1500_20dhold 11.5 0.5 49 20020103 20241108 10.7 all GAscore=7
Gscore_top25_SP1500_20dhold 12.5 0.5 83 20020103 20241108 mix of Gscore=6 and 7
SP500MktCapWeight 9.6 0.0 499 20020103 20241108 9.4


There is not much space between GAscore and Gscore results, and so it's difficult to say which one P123 is using. (There are more than 25 GAscore=7 stocks, with an average count of 49 passing stocks. There are sometimes fewer than 25 Gscore=7 stocks, and so the screen sometimes adds in Gscore=6 picks.)


Rerunning a rolling backtest(multiple start dates) 11/11/2014 – 11/11/2024
523 Samples, Start Frequency every Week, Holding Period 3 Months:
Scrn SP500
Annualized 20.06% 13.33%


The 20.1 CAGR is higher than the gtr1 results:

           screen             CAGR  SDcg  depth    from       to     P123
GAscore_top25_SP1500_20dhold 10.8 0.9 51 20141111 20241108
Gscore_top25_SP1500_20dhold 16.2 0.7 91 20141111 20241108 20.1
SP500MktCapWeight 13.5 0.0 500 20141111 20241108 13.3


Growth stocks have higher returns recently, and so Gscore_top25 has higher returns.

Having an explicit tie break would make comparisons easier. For example, using price as a tie break makes the depth a consistent 25:
Price > 1
SortField = Gscore + 1/Price
SortField top 25

               Screen                 CAGR  SDcg  Depth    From       To
GAscoreLowPrice_top25_SP1500_20dhold 9.3 0.5 25 20141111 20241108
GscoreLowPrice_top25_SP1500_20dhold 16.7 0.9 25 20141111 20241108

Print the post


Author: lizgdal   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/11/2024 8:45 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 2
Growth stocks (BP bottom 20%) have higher CAGR in the last 10 years:

      Screen       CAGR  GSD  MDD  Sharpe  Beta    From       To     Depth
SP1500BPq1 7.6 34 -60 0.34 1.4 20141111 20241108 298 BP top 20%
SP1500BPq2 8.9 24 -46 0.44 1.1 20141111 20241108 298
SP1500BPq3 9.0 22 -41 0.47 1.1 20141111 20241108 295
SP1500BPq4 10.4 20 -37 0.56 1.1 20141111 20241108 298
SP1500BPq5 13.2 21 -37 0.68 1.1 20141111 20241108 298 BP btm 20%
SP1500EqualWeight 10.3 23 -42 0.51 1.1 20141111 20241108 1499



Print the post


Author: Aussi   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/11/2024 10:09 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 0
A SAWR of > 10% is perhaps the highest I have seen for an annual screen.

Aussi
Print the post


Author: musselmant   😊 😞
Number: of 15059 
Subject: Re: G-score backtest
Date: 11/12/2024 6:04 PM
Post Reply | Report Post | Recommend It!
No. of Recommendations: 2
the top 5 of the Nasdaq100 ranked by 200 day return generates a 18% CAGR with annual trading.
Print the post


Post New
Unthreaded | Threaded | Whole Thread (12) |


Announcements
Berkshire Hathaway FAQ
Contact Shrewd'm
Contact the developer of these message boards.

Best Of BRK.A | Best Of | Favourites & Replies | All Boards | Followed Shrewds