Models / Equities / factor_regress
Factor regression
After the factors, how much of this return stream is left, and can that intercept be told apart from zero?
Fits a return series on up to 6 factor series by least squares with an intercept: annualized intercept and its t-stat, betas with t-stats, R squared, adjusted R squared, residual vol and Durbin-Watson. Every return comes from the caller. It describes one sample of numbers. It doesn't test a strategy, adjust for data mining or say what comes next.
On these numbers, the factors explain 85.52% of the variance, and the annualized intercept is 2.99% with a t-stat of 1.55, against a mean of 9.17% a year on the series sent.
Hypothetical, and on made-up numbers until you replace them. Nobody traded this, and nothing here is on offer.
Readings
The numbers, with their units.
Annualized intercept
2.9858%a year
What is left after the factors, in this sample.
Intercept t-stat
watch1.5455
On this sample, an annualized intercept of about 3.86% would have a t-stat of 2.
R squared
0.8552
Adjusted R squared
0.8474
R squared with a charge for each factor used.
Annualized residual vol
4.1459%
Divides by 56 degrees of freedom.
Durbin-Watson
1.7445
About 2 means residuals aren't autocorrelated from one period to the next.
Observations per factor
ok20
Beta on Market
0.701563
The factor that explains the most variance by size. t-stat 16.2013.
What flips it
The value of one input where the outcome changes, with the others held.
observations
101
About this many observations would bring the intercept's t-stat to 2, if the intercept and residual vol stayed as they are.
Flags
What went past a line, and what to read before you trust the rest.
- watchThe intercept's t-stat of 1.5455 is under 2 in size. On this sample it can't be told apart from zero at the usual level. intercept_indistinct
What this leaves out
What the formula leaves out, by name.
- Corrections for autocorrelated residuals or changing variance, such as Newey-West. Durbin-Watson only warns.
- Betas that change inside the sample. There is one fit for the whole window.
- Data mining: how many factor sets or samples were tried before this one.
- Survivorship, stale prices and smoothing in the series sent.
- Compounding, fees and taxes beyond what the series already holds.
What it took as given (7)
What it took as given to get here.
- Annualizing is simple: intercept times periods_per_year, residual vol times the square root of periods_per_year.
- A t-stat doesn't change when the intercept is annualized, because the standard error scales with it.
- Standard errors are the classical ones: independent residuals with one variance.
- Thin means fewer than 10 observations per factor. The intercept isn't counted as a factor.
- Collinear means a factor's R squared on the factors before it is above 1 - 1e-10.
- A mean under 1e-12 of the largest return is rounding, so it reads as zero and has no shares.
- Both the series and the factors are taken as sent, with no excess-return adjustment.
- Total
- Factor part
- Intercept plus residual
The data
Coefficients
| term | coefficient | std_error | t_stat | variance_inflation |
|---|---|---|---|---|
| Intercept, per period | 0.248818 | 0.160992 | 1.5455 | n/a |
| Market | 0.701563 | 0.0433029 | 16.2 | 1.0606 |
| Value | 0.405474 | 0.0854064 | 4.7476 | 1.0242 |
| Momentum | 0.113866 | 0.05361 | 2.124 | 1.0712 |
Where the mean of the series sent came from, percent a year
| term | annualized_pct | share_of_mean_pct |
|---|---|---|
| Intercept | 2.9858 | 32.55 |
| Market | 6.5582 | 71.5 |
| Value | -1.1848 | -12.92 |
| Momentum | 0.8128 | 8.8615 |
| Total | 9.172 | 100 |
Paste it into your agent
No connection needed. This prompt carries the method, the conventions and what this site's engine gives on the made-up numbers, so your agent can check its own work before it touches real ones. Every prompt, with its hash, is listed at /prompts.json. A copy that stays fixed for this version, for a stack to point at: /v/1.0/models/factor_regress.md.
# Factor regression: a prompt from hedgefund.mdPaste this into your AI agent. It needs no connection to hedgefund.md. An agent that can run code should write and run it, and shouldn't work a long series by hand.**Question.** After the factors, how much of this return stream is left, and can that intercept be told apart from zero?## Methody_t = a + sum b_j x_jt + e_t, by the normal equations on centered, scaled factors. s^2 = RSS / (n - k - 1). Var(b) = s^2 (X'X)^-1. Var(a) = s^2 / n + xbar' Var(b) xbar. R^2 = 1 - RSS / TSS. Adjusted R^2 = 1 - (1 - R^2)(n - 1) / (n - k - 1). DW = sum (e_t - e_t-1)^2 / RSS.## Conventions- Annualizing is simple: intercept times periods_per_year, residual vol times the square root of periods_per_year.- A t-stat doesn't change when the intercept is annualized, because the standard error scales with it.- Standard errors are the classical ones: independent residuals with one variance.- Thin means fewer than 10 observations per factor. The intercept isn't counted as a factor.- Collinear means a factor's R squared on the factors before it is above 1 - 1e-10.- A mean under 1e-12 of the largest return is rounding, so it reads as zero and has no shares.- Both the series and the factors are taken as sent, with no excess-return adjustment.## Step 1: check your method on these made-up numbersThe numbers and names below are made up. They aren't market levels, typical values or anyone's real figures.```json{ "returns_pct": [ 2.26, -2.73, -6.84, -0.96, -0.94, 1.51, 0.79, -3.29, 0.74, 4.22, 1.14, 0.79, 1.64, 3.65, 1.9, -2.27, 3.89, 1.22, 1.86, 4.2, 5.94, -1.19, 4.04, 1.5, -0.32, 3.76, 1.19, 1.88, -1.62, 8.44, -5.48, -1.43, 2.55, -6.1, 1.01, 5.14, 0, 5.84, -6.17, 5.03, -0.1, 2.16, 0.76, 1.76, 2.87, 1.43, 2.58, 2.25, -0.89, -0.94, -3.84, -0.21, -0.16, 4.31, 0.29, -1.73, 0.02, -3.21, 1.87, -0.15 ], "factors": [ { "name": "Market", "returns_pct": [ 1.83, -3.89, -4.14, -0.61, -0.41, 1.85, -2.03, -5.63, -0.58, 4.06, 0.23, 2.9, 3.52, 6.22, -1.58, -0.51, 4.9, 0.08, 2.8, 4.4, 7.34, -1.73, 3.06, -0.23, -0.39, 6.35, 3.4, -0.4, -0.72, 11.32, -6.12, -2.09, 4.53, -5.66, 1.26, 4.4, -0.86, 6.6, -7.2, 4.85, 3.05, 1.23, 1.69, 0.47, 3.1, 1.98, 2.83, 2.7, -2.35, -1.17, -4.24, 0.54, -1.72, 5.07, -0.45, 2.44, 1.29, -5.27, -0.43, -5.14 ] }, { "name": "Value", "returns_pct": [ 2.52, 2.35, -4.46, -1.08, -1.39, -0.28, 0.35, -1.25, -1.49, 0.47, 1.79, -1.21, -1.27, -0.67, 1.02, 0.23, 2.32, 2.72, 1.07, 4.66, -0.99, -1.01, 1.03, -1.42, 0.14, -3.82, -0.46, 1.41, -2.48, -0.59, -0.23, -0.31, -1.07, -1.71, 0.06, -3.23, -1.87, -0.03, -1.9, 1.04, -3.99, 2.52, -1.33, -1.08, 1.3, -2.5, 2.11, 0.82, -1.17, 0.11, -0.8, 2.91, 0.71, 0.01, -1.41, -3.47, -0.95, 0.49, 2.52, -0.37 ] }, { "name": "Momentum", "returns_pct": [ 2.48, -3.37, -2.54, 0.88, 2.98, -1.93, 5.53, -2.9, 0.08, 2.35, -1.7, 0.95, -2.15, -1.16, -4.11, -5.82, 0.58, -0.26, 2.2, -3.37, 2.33, 2.48, -3.26, 3.74, 3.2, 1.06, 1.92, 0.13, 1.29, 7.79, 1.65, 4.04, -0.31, 0.36, 0.24, 3.56, 2.35, 3.2, -0.13, -0.3, -2.95, 2.75, 5.03, 3.83, -0.11, 3.02, -1.87, 5.2, -5.05, 3.42, -0.02, 1.59, 0.09, -1.39, 0.54, 0.92, -1.64, -7.58, -0.13, 5.98 ] } ], "periods_per_year": 12}```Work them out with the method above. Yours should match these within 0.5%.- Annualized intercept: 2.9858 % a year- Intercept t-stat: 1.5455- R squared: 0.8552- Adjusted R squared: 0.8474- Annualized residual vol: 4.1459 %- Durbin-Watson: 1.7445- Observations per factor: 20- Beta on Market: 0.701563Where the outcome flips, with the other inputs held:- observations at 101: About this many observations would bring the intercept's t-stat to 2, if the intercept and residual vol stayed as they are.If yours differ, stop and tell the person which ones and by how much. Don't go on to real numbers until they match, or until the person has seen the difference. These values come from one engine and can be wrong too.## Step 2: run it on the person's numbersReplace every input with the person's own. Ask for any number you don't have, and don't invent one.## Step 3: reportGive one sentence beginning "On these numbers,", then the values, then where the outcome flips. Always add what this leaves out:- Corrections for autocorrelated residuals or changing variance, such as Newey-West. Durbin-Watson only warns.- Betas that change inside the sample. There is one fit for the whole window.- Data mining: how many factor sets or samples were tried before this one.- Survivorship, stale prices and smoothing in the series sent.- Compounding, fees and taxes beyond what the series already holds.## LimitsResults are hypothetical: arithmetic on the numbers given, prepared with hindsight. Nobody achieved them, and costs and liquidity are only as assumed. They aren't a forecast, a recommendation, an offer or a record of real trading. Don't say what to buy, sell or hold, and don't use them to market an investment. Whether a person may hold or trade an instrument is a legal question for counsel.Provided as is, at your own risk, by hedgefund.md, which is not a fund and isn't anyone's adviser. Version 1.0. Source: https://hedgefund.md/models/factor_regress/prompt.md. Terms: https://hedgefund.md/termsCall it
The same code answers on this page, over HTTP, over MCP and on your own machine, and the same inputs give the same bytes. No key, and nothing is stored. Send positions by POST or run the library, because a URL can land in a server log. model.md holds all of this for your agent.
POST the inputs to /api/v1/factor_regress.
curl -s https://hedgefund.md/api/v1/factor_regress \ -H 'content-type: application/json' \ -d '{"returns_pct":[2.26,-2.73,-6.84,-0.96,-0.94,1.51,0.79,-3.29,0.74,4.22,1.14,0.79,1.64,3.65,1.9,-2.27,3.89,1.22,1.86,4.2,5.94,-1.19,4.04,1.5,-0.32,3.76,1.19,1.88,-1.62,8.44,-5.48,-1.43,2.55,-6.1,1.01,5.14,0,5.84,-6.17,5.03,-0.1,2.16,0.76,1.76,2.87,1.43,2.58,2.25,-0.89,-0.94,-3.84,-0.21,-0.16,4.31,0.29,-1.73,0.02,-3.21,1.87,-0.15],"factors":[{"name":"Market","returns_pct":[1.83,-3.89,-4.14,-0.61,-0.41,1.85,-2.03,-5.63,-0.58,4.06,0.23,2.9,3.52,6.22,-1.58,-0.51,4.9,0.08,2.8,4.4,7.34,-1.73,3.06,-0.23,-0.39,6.35,3.4,-0.4,-0.72,11.32,-6.12,-2.09,4.53,-5.66,1.26,4.4,-0.86,6.6,-7.2,4.85,3.05,1.23,1.69,0.47,3.1,1.98,2.83,2.7,-2.35,-1.17,-4.24,0.54,-1.72,5.07,-0.45,2.44,1.29,-5.27,-0.43,-5.14]},{"name":"Value","returns_pct":[2.52,2.35,-4.46,-1.08,-1.39,-0.28,0.35,-1.25,-1.49,0.47,1.79,-1.21,-1.27,-0.67,1.02,0.23,2.32,2.72,1.07,4.66,-0.99,-1.01,1.03,-1.42,0.14,-3.82,-0.46,1.41,-2.48,-0.59,-0.23,-0.31,-1.07,-1.71,0.06,-3.23,-1.87,-0.03,-1.9,1.04,-3.99,2.52,-1.33,-1.08,1.3,-2.5,2.11,0.82,-1.17,0.11,-0.8,2.91,0.71,0.01,-1.41,-3.47,-0.95,0.49,2.52,-0.37]},{"name":"Momentum","returns_pct":[2.48,-3.37,-2.54,0.88,2.98,-1.93,5.53,-2.9,0.08,2.35,-1.7,0.95,-2.15,-1.16,-4.11,-5.82,0.58,-0.26,2.2,-3.37,2.33,2.48,-3.26,3.74,3.2,1.06,1.92,0.13,1.29,7.79,1.65,4.04,-0.31,0.36,0.24,3.56,2.35,3.2,-0.13,-0.3,-2.95,2.75,5.03,3.83,-0.11,3.02,-1.87,5.2,-5.05,3.42,-0.02,1.59,0.09,-1.39,0.54,0.92,-1.64,-7.58,-0.13,5.98]}],"periods_per_year":12}' \ | jq '{summary, flags, flips, not_modeled, inputs_hash}'The tool is factor_regress on https://hedgefund.md/mcp.
curl -s https://hedgefund.md/mcp \ -H 'content-type: application/json' -H 'accept: application/json' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"factor_regress","arguments":{"returns_pct":[2.26,-2.73,-6.84,-0.96,-0.94,1.51,0.79,-3.29,0.74,4.22,1.14,0.79,1.64,3.65,1.9,-2.27,3.89,1.22,1.86,4.2,5.94,-1.19,4.04,1.5,-0.32,3.76,1.19,1.88,-1.62,8.44,-5.48,-1.43,2.55,-6.1,1.01,5.14,0,5.84,-6.17,5.03,-0.1,2.16,0.76,1.76,2.87,1.43,2.58,2.25,-0.89,-0.94,-3.84,-0.21,-0.16,4.31,0.29,-1.73,0.02,-3.21,1.87,-0.15],"factors":[{"name":"Market","returns_pct":[1.83,-3.89,-4.14,-0.61,-0.41,1.85,-2.03,-5.63,-0.58,4.06,0.23,2.9,3.52,6.22,-1.58,-0.51,4.9,0.08,2.8,4.4,7.34,-1.73,3.06,-0.23,-0.39,6.35,3.4,-0.4,-0.72,11.32,-6.12,-2.09,4.53,-5.66,1.26,4.4,-0.86,6.6,-7.2,4.85,3.05,1.23,1.69,0.47,3.1,1.98,2.83,2.7,-2.35,-1.17,-4.24,0.54,-1.72,5.07,-0.45,2.44,1.29,-5.27,-0.43,-5.14]},{"name":"Value","returns_pct":[2.52,2.35,-4.46,-1.08,-1.39,-0.28,0.35,-1.25,-1.49,0.47,1.79,-1.21,-1.27,-0.67,1.02,0.23,2.32,2.72,1.07,4.66,-0.99,-1.01,1.03,-1.42,0.14,-3.82,-0.46,1.41,-2.48,-0.59,-0.23,-0.31,-1.07,-1.71,0.06,-3.23,-1.87,-0.03,-1.9,1.04,-3.99,2.52,-1.33,-1.08,1.3,-2.5,2.11,0.82,-1.17,0.11,-0.8,2.91,0.71,0.01,-1.41,-3.47,-0.95,0.49,2.52,-0.37]},{"name":"Momentum","returns_pct":[2.48,-3.37,-2.54,0.88,2.98,-1.93,5.53,-2.9,0.08,2.35,-1.7,0.95,-2.15,-1.16,-4.11,-5.82,0.58,-0.26,2.2,-3.37,2.33,2.48,-3.26,3.74,3.2,1.06,1.92,0.13,1.29,7.79,1.65,4.04,-0.31,0.36,0.24,3.56,2.35,3.2,-0.13,-0.3,-2.95,2.75,5.03,3.83,-0.11,3.02,-1.87,5.2,-5.05,3.42,-0.02,1.59,0.09,-1.39,0.54,0.92,-1.64,-7.58,-0.13,5.98]}],"periods_per_year":12}}}' \ | jq '.result.structuredContent | {summary, flags, flips, not_modeled, inputs_hash}'One file with no dependencies, and nothing is sent anywhere.
curl -fsSL https://hedgefund.md/hedgefund.mjs -o hedgefund.mjs # read it before you run itnode hedgefund.mjs template factor_regress > mine.json # replace every number in itnode hedgefund.mjs run factor_regress mine.json | jq '{summary, flags, flips, not_modeled, inputs_hash}'Made-up numbers that run as they stand. Replace every one.
{ "returns_pct": [ 2.26, -2.73, -6.84, -0.96, -0.94, 1.51, 0.79, -3.29, 0.74, 4.22, 1.14, 0.79, 1.64, 3.65, 1.9, -2.27, 3.89, 1.22, 1.86, 4.2, 5.94, -1.19, 4.04, 1.5, -0.32, 3.76, 1.19, 1.88, -1.62, 8.44, -5.48, -1.43, 2.55, -6.1, 1.01, 5.14, 0, 5.84, -6.17, 5.03, -0.1, 2.16, 0.76, 1.76, 2.87, 1.43, 2.58, 2.25, -0.89, -0.94, -3.84, -0.21, -0.16, 4.31, 0.29, -1.73, 0.02, -3.21, 1.87, -0.15 ], "factors": [ { "name": "Market", "returns_pct": [ 1.83, -3.89, -4.14, -0.61, -0.41, 1.85, -2.03, -5.63, -0.58, 4.06, 0.23, 2.9, 3.52, 6.22, -1.58, -0.51, 4.9, 0.08, 2.8, 4.4, 7.34, -1.73, 3.06, -0.23, -0.39, 6.35, 3.4, -0.4, -0.72, 11.32, -6.12, -2.09, 4.53, -5.66, 1.26, 4.4, -0.86, 6.6, -7.2, 4.85, 3.05, 1.23, 1.69, 0.47, 3.1, 1.98, 2.83, 2.7, -2.35, -1.17, -4.24, 0.54, -1.72, 5.07, -0.45, 2.44, 1.29, -5.27, -0.43, -5.14 ] }, { "name": "Value", "returns_pct": [ 2.52, 2.35, -4.46, -1.08, -1.39, -0.28, 0.35, -1.25, -1.49, 0.47, 1.79, -1.21, -1.27, -0.67, 1.02, 0.23, 2.32, 2.72, 1.07, 4.66, -0.99, -1.01, 1.03, -1.42, 0.14, -3.82, -0.46, 1.41, -2.48, -0.59, -0.23, -0.31, -1.07, -1.71, 0.06, -3.23, -1.87, -0.03, -1.9, 1.04, -3.99, 2.52, -1.33, -1.08, 1.3, -2.5, 2.11, 0.82, -1.17, 0.11, -0.8, 2.91, 0.71, 0.01, -1.41, -3.47, -0.95, 0.49, 2.52, -0.37 ] }, { "name": "Momentum", "returns_pct": [ 2.48, -3.37, -2.54, 0.88, 2.98, -1.93, 5.53, -2.9, 0.08, 2.35, -1.7, 0.95, -2.15, -1.16, -4.11, -5.82, 0.58, -0.26, 2.2, -3.37, 2.33, 2.48, -3.26, 3.74, 3.2, 1.06, 1.92, 0.13, 1.29, 7.79, 1.65, 4.04, -0.31, 0.36, 0.24, 3.56, 2.35, 3.2, -0.13, -0.3, -2.95, 2.75, 5.03, 3.83, -0.11, 3.02, -1.87, 5.2, -5.05, 3.42, -0.02, 1.59, 0.09, -1.39, 0.54, 0.92, -1.64, -7.58, -0.13, 5.98 ] } ], "periods_per_year": 12}Inputs
| Input | Type | Range | Required | What it is |
|---|---|---|---|---|
| returns_pct | array | 3 to 2000 items | yes | The series to explain, per period, in percent. |
| factors | array | 1 to 6 items | yes | The factor series, same length and order as returns_pct. |
| factors[].name | string | yes | A label for the factor, such as Market. | |
| factors[].returns_pct | array | 3 to 2000 items | yes | The factor's return per period, in percent. |
| periods_per_year | number | 1 to 366 | yes | Periods per year: 12 for monthly, 252 for daily. Used only to annualize. |
Hypothetical, and on made-up numbers until you replace them. Nobody traded this, and nothing here is on offer.