Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Makakahanap ba ang LLM ng Alpha Factors?

Makakasulat ang LLM ng sandaang alpha factor sa isang oras. Tingnan kung paano umiskor ang 240 coin-flip factor sa sampung taon ng tunay na presyo at paano subukan ang mga nakaligtas.

Isang LLM ang maaaring buong araw na magmungkahi ng mga alpha factor. Bigyan ang isang mahusay na model ng data dictionary at scoring harness, at makapagsusulat ito ng sandaang kapani-paniwalang factor expression bago magtanghali. Mas mahirap ang nakapaloob na tanong: paano malalaman kung tunay ang isa sa mga iyon, kung ang search na lumikha rito ay isang makina para bumuo ng mga winner mula sa noise?

Ano ang alpha factor?

Ang factor ay isang panuntunang ginagawang isang numero ang market data para sa bawat stock sa bawat petsa. Factor ang pagbabago ng presyo sa loob ng labindalawang buwan. Gayundin ang ratio ng debt sa equity. Nagiging strategy ang factor kapag niraranggo mo ang isang universe batay rito, binibili ang nangungunang bahagi, ibinibenta ang pinakamababang bahagi, at nagre-rebalance ayon sa isang iskedyul. Ang alpha ay anumang return na natitira matapos ibawas ang return na ibibigay sana ng simpleng market exposure.

Ang mga candidate ay binibigyan ng score gamit ang Sharpe ratio: average return na hinati sa standard deviation ng return na iyon, at ina-annualize. Ito ang return kada unit ng paggalaw. Kagalang-galang ang long-run Sharpe na malapit sa 1 sa isang live strategy. Dapat itong tandaan sa susunod na makakita ka ng backtest na may Sharpe na 3.

Paano talaga gumagana ang LLM factor research

Bawat project sa larangang ito ay may bersyon ng parehong loop.

  1. Nagsusulat ang model ng factor expression sa isang maliit na language na kayang i-evaluate ng harness.
  2. Binibigyan ng backtester ng score ang bawat expression gamit ang nakatakdang history ng mga presyo at fundamentals.
  3. Pinananatili ang mga expression na lampas sa score threshold. Inaalis ang iba.
  4. Ibinabalik sa context ng model ang mga napanatili bilang worked examples, at muling pinapatakbo ang loop.

Hinahati ng Multi-agent trading systems ang mga trabahong ito sa magkakahiwalay na role: may nagmumungkahi at may nagte-test. Tunay na kapaki-pakinabang ang plumbing, at pareho ang market data skills na kailangan ng isang AI agent at ng isang tao.

Walang hindi tapat sa loop. Bahagi ng research ang search. Ang problema ay arithmetic, at lumilitaw ito kapag higit sa ilang beses nang pinapatakbo ang step 2.

Isang price history. Libo-libong murang hypothesis. Lahat ng hypothesis ay sinusukat laban sa parehong finite sample, at malaki ang papel ng swerte sa sample na iyon. Kapag sapat ang dami ng rules na sinubukan, may ilan na malapit na magfi-fit sa swerte. Hindi matutukoy ng score kung anong uri ng fit ang nakuha mo, dahil pareho ang numerong ipinapakita ng rule na tumugma sa noise at ng rule na tumugma sa market.

Narito ang null hypothesis, na 240 beses iginuhit. Ang bawat “factor” sa ibaba ay coin flip: isang hash ng ticker, buwan, at trial number ang naghahati sa 40 malalaking US name sa dalawang bahagi bawat buwan, at nagho-hold ang strategy ng long position sa isang bahagi at short position sa kabila. Walang information dito, ayon sa pagkakagawa. Sinukat gamit ang tunay na month-end returns mula January 2016 hanggang June 2021, ganito ang naging resulta ng 240 trials.

Query240 coin flip factors na sinukat sa aktuwal na presyo: annualized Sharpe, Ene 2016 hanggang Hun 2021
Ang eksaktong SQL sa likod ng bawat numero
WITH month_end AS (
    SELECT ticker,
           toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL','ADBE','AMZN','BA','CAT','COST','CRM','CSCO','CVX','DE',
                     'DUK','GE','GOOGL','HD','HON','IBM','INTC','JNJ','JPM','KO',
                     'LMT','MCD','MMM','MRK','MSFT','NKE','NVDA','ORCL','PEP','PFE',
                     'PG','QCOM','SO','T','TGT','TXN','UNP','VZ','WMT','XOM')
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2021-06-30')
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) >= 22
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY ticker, month_start
),
lagged AS (
    SELECT ticker,
           month_start,
           close_px,
           lagInFrame(close_px) OVER (PARTITION BY ticker ORDER BY month_start
                                      ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px
    FROM month_end
),
monthly_return AS (
    SELECT ticker, month_start, close_px / prev_px - 1 AS ret
    FROM lagged
    WHERE prev_px > 0
      AND month_start >= toDate('2016-01-01')
),
trial AS (
    SELECT arrayJoin(range(1, 241)) AS n
),
factor_month AS (
    SELECT t.n AS trial_id,
           m.month_start AS month_start,
           avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1)
         - avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) AS long_short_ret
    FROM monthly_return AS m
    CROSS JOIN trial AS t
    GROUP BY trial_id, month_start
    HAVING countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1) > 0
       AND countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) > 0
),
scored AS (
    SELECT trial_id,
           avg(long_short_ret) / stddevSamp(long_short_ret) * sqrt(12) AS sharpe
    FROM factor_month
    GROUP BY trial_id
    HAVING stddevSamp(long_short_ret) > 0
)
SELECT multiIf(sharpe < -1.2, 'below -1.2',
               sharpe < -0.8, '-1.2 to -0.8',
               sharpe < -0.4, '-0.8 to -0.4',
               sharpe <  0.0, '-0.4 to 0.0',
               sharpe <  0.4, '0.0 to 0.4',
               sharpe <  0.8, '0.4 to 0.8',
               sharpe <  1.2, '0.8 to 1.2',
               '1.2 and above') AS sharpe_bucket,
       count() AS factor_count,
       round(100 * count() / 240, 1) AS share_pct
FROM scored
GROUP BY sharpe_bucket
ORDER BY min(sharpe)
Run this yourself

Ang spread ang mahalagang punto. Walang ipinapakitang predictive power ang chart na iyon, ngunit 1 trials ang napunta sa top band (1.2 and above), 0.4% ng search, at 1 sa bottom band (below -1.2). Ang researcher na nagpatakbo ng isang masuwerteng trial at tumigil ay magkakaroon ng chart at Sharpe ratio, ngunit walang paraan upang malaman kung discovery ba ang mga ito. Dito, ang returns ay mula month-end close hanggang sa susunod na month-end close; ipinapaliwanag ng kung paano sinusukat ang monthly returns ang arithmetic na iyon.

Ang mahalagang numero ay kung ilan ang sinubukan mo

Kulang ng denominator ang isang backtest na iniulat nang mag-isa. Basahin ang parehong 240 trials bilang isang search na patuloy na lumalawak: sa bawat hakbang, ipinapakita ang pinakamataas na score sa board kasabay ng average ng lahat ng nasubukan hanggang sa puntong iyon.

QueryTumataas ang best score kasabay ng laki ng search: best at average Sharpe ayon sa bilang ng trials
Ang eksaktong SQL sa likod ng bawat numero
WITH month_end AS (
    SELECT ticker,
           toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL','ADBE','AMZN','BA','CAT','COST','CRM','CSCO','CVX','DE',
                     'DUK','GE','GOOGL','HD','HON','IBM','INTC','JNJ','JPM','KO',
                     'LMT','MCD','MMM','MRK','MSFT','NKE','NVDA','ORCL','PEP','PFE',
                     'PG','QCOM','SO','T','TGT','TXN','UNP','VZ','WMT','XOM')
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2021-06-30')
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) >= 22
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY ticker, month_start
),
lagged AS (
    SELECT ticker,
           month_start,
           close_px,
           lagInFrame(close_px) OVER (PARTITION BY ticker ORDER BY month_start
                                      ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px
    FROM month_end
),
monthly_return AS (
    SELECT ticker, month_start, close_px / prev_px - 1 AS ret
    FROM lagged
    WHERE prev_px > 0
      AND month_start >= toDate('2016-01-01')
),
trial AS (
    SELECT arrayJoin(range(1, 241)) AS n
),
factor_month AS (
    SELECT t.n AS trial_id,
           m.month_start AS month_start,
           avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1)
         - avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) AS long_short_ret
    FROM monthly_return AS m
    CROSS JOIN trial AS t
    GROUP BY trial_id, month_start
    HAVING countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1) > 0
       AND countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) > 0
),
scored AS (
    SELECT trial_id,
           avg(long_short_ret) / stddevSamp(long_short_ret) * sqrt(12) AS sharpe
    FROM factor_month
    GROUP BY trial_id
    HAVING stddevSamp(long_short_ret) > 0
),
ladder AS (
    SELECT arrayJoin([1, 2, 5, 10, 25, 50, 100, 160, 240]) AS n
)
SELECT l.n AS factors_tried,
       round(max(s.sharpe), 2) AS best_sharpe,
       round(avg(s.sharpe), 2) AS average_sharpe
FROM ladder AS l
CROSS JOIN scored AS s
WHERE s.trial_id <= l.n
GROUP BY factors_tried
ORDER BY factors_tried
Run this yourself

Maaari lamang tumaas ang running maximum, at iyon mismo ang bitag. Ang unang sinubukang rule ay may score na 0.44. Pagkatapos ng 240 trials, ang pinakamataas sa board ay 1.59, habang ang average ng lahat ng ito ay 0.01. Gumanda ang headline nang walang isang rule na gumanda. Ang harness na nag-e-evaluate ng sampung libong expression ay nagpapatakbo ng curve na ito nang mas malayo sa kanan kaysa sa ipinakita rito, at ang nirereport nitong numero ay ang pinakamataas na punto nito.

Ano ang ginagawa ng held-out period sa mga winner

Ang karaniwang depensa ay holdout: sinusukat ang score sa isang period, pagkatapos ay muling sinusukat ang mga nakaligtas sa mas huling period na hindi nakita ng search. Kunin ang labindalawang pinakamahusay na coin flip mula sa training window at patakbuhin ang parehong rules sa limang taon pagkatapos nito, mula July 2021 hanggang June 2026.

QueryAng labindalawang best trial sa training, muling sinukat sa limang hindi ginalaw na taon (Hul 2021 hanggang Hun 2026)
Ang eksaktong SQL sa likod ng bawat numero
WITH month_end AS (
    SELECT ticker,
           toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL','ADBE','AMZN','BA','CAT','COST','CRM','CSCO','CVX','DE',
                     'DUK','GE','GOOGL','HD','HON','IBM','INTC','JNJ','JPM','KO',
                     'LMT','MCD','MMM','MRK','MSFT','NKE','NVDA','ORCL','PEP','PFE',
                     'PG','QCOM','SO','T','TGT','TXN','UNP','VZ','WMT','XOM')
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30')
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) >= 22
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY ticker, month_start
),
lagged AS (
    SELECT ticker,
           month_start,
           close_px,
           lagInFrame(close_px) OVER (PARTITION BY ticker ORDER BY month_start
                                      ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px
    FROM month_end
),
monthly_return AS (
    SELECT ticker, month_start, close_px / prev_px - 1 AS ret
    FROM lagged
    WHERE prev_px > 0
      AND month_start >= toDate('2016-01-01')
),
trial AS (
    SELECT arrayJoin(range(1, 241)) AS n
),
factor_month AS (
    SELECT t.n AS trial_id,
           m.month_start AS month_start,
           avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1)
         - avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) AS long_short_ret
    FROM monthly_return AS m
    CROSS JOIN trial AS t
    GROUP BY trial_id, month_start
    HAVING countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1) > 0
       AND countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) > 0
),
scored AS (
    SELECT trial_id,
           avgIf(long_short_ret, month_start <  toDate('2021-07-01'))
             / stddevSampIf(long_short_ret, month_start <  toDate('2021-07-01')) * sqrt(12) AS in_sample_sharpe,
           avgIf(long_short_ret, month_start >= toDate('2021-07-01'))
             / stddevSampIf(long_short_ret, month_start >= toDate('2021-07-01')) * sqrt(12) AS out_of_sample_sharpe
    FROM factor_month
    GROUP BY trial_id
    HAVING countIf(month_start <  toDate('2021-07-01')) >= 24
       AND countIf(month_start >= toDate('2021-07-01')) >= 24
)
SELECT concat('trial ', toString(trial_id)) AS factor_label,
       round(in_sample_sharpe, 2) AS in_sample_sharpe,
       round(out_of_sample_sharpe, 2) AS out_of_sample_sharpe
FROM scored
ORDER BY in_sample_sharpe DESC
LIMIT 12
Run this yourself

Ang bawat pares ng bar ay isang rule. Ang kaliwang bar ang score na nagbigay rito ng puwesto sa report. Ang kanang bar ang score ng parehong rule sa sumunod na limang taon. Ang trial na nanguna ay may score na 1.59 sa training at -0.51 pagkatapos; ang ikalabindalawa ay may 0.74 at pagkatapos ay 0.49.

Maliit na sample din ang labindalawang rule. Mas malinaw ang resulta kung paghihiwalayin ang lahat ng 240 sa fifths batay sa training score, at kukunin ang average holdout score ng bawat fifth.

QueryRanggo sa training kumpara sa resulta sa holdout: 240 trial na hinati sa tig-limang pangkat
Ang eksaktong SQL sa likod ng bawat numero
WITH month_end AS (
    SELECT ticker,
           toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,
           argMax(toFloat64(close), window_start) AS close_px
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL','ADBE','AMZN','BA','CAT','COST','CRM','CSCO','CVX','DE',
                     'DUK','GE','GOOGL','HD','HON','IBM','INTC','JNJ','JPM','KO',
                     'LMT','MCD','MMM','MRK','MSFT','NKE','NVDA','ORCL','PEP','PFE',
                     'PG','QCOM','SO','T','TGT','TXN','UNP','VZ','WMT','XOM')
      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')
      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2026-06-30')
      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) >= 22
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
    GROUP BY ticker, month_start
),
lagged AS (
    SELECT ticker,
           month_start,
           close_px,
           lagInFrame(close_px) OVER (PARTITION BY ticker ORDER BY month_start
                                      ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px
    FROM month_end
),
monthly_return AS (
    SELECT ticker, month_start, close_px / prev_px - 1 AS ret
    FROM lagged
    WHERE prev_px > 0
      AND month_start >= toDate('2016-01-01')
),
trial AS (
    SELECT arrayJoin(range(1, 241)) AS n
),
factor_month AS (
    SELECT t.n AS trial_id,
           m.month_start AS month_start,
           avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1)
         - avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) AS long_short_ret
    FROM monthly_return AS m
    CROSS JOIN trial AS t
    GROUP BY trial_id, month_start
    HAVING countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1) > 0
       AND countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) > 0
),
scored AS (
    SELECT trial_id,
           avgIf(long_short_ret, month_start <  toDate('2021-07-01'))
             / stddevSampIf(long_short_ret, month_start <  toDate('2021-07-01')) * sqrt(12) AS in_sample_sharpe,
           avgIf(long_short_ret, month_start >= toDate('2021-07-01'))
             / stddevSampIf(long_short_ret, month_start >= toDate('2021-07-01')) * sqrt(12) AS out_of_sample_sharpe
    FROM factor_month
    GROUP BY trial_id
    HAVING countIf(month_start <  toDate('2021-07-01')) >= 24
       AND countIf(month_start >= toDate('2021-07-01')) >= 24
),
ranked AS (
    SELECT trial_id,
           in_sample_sharpe,
           out_of_sample_sharpe,
           row_number() OVER (ORDER BY in_sample_sharpe DESC) AS in_sample_rank
    FROM scored
)
SELECT multiIf(in_sample_rank <=  48, 'best fifth in training',
               in_sample_rank <=  96, 'second fifth',
               in_sample_rank <= 144, 'middle fifth',
               in_sample_rank <= 192, 'fourth fifth',
               'worst fifth in training') AS training_group,
       round(avg(in_sample_sharpe), 2) AS avg_in_sample_sharpe,
       round(avg(out_of_sample_sharpe), 2) AS avg_out_of_sample_sharpe
FROM ranked
GROUP BY training_group
ORDER BY min(in_sample_rank)
Run this yourself

Sa training, mula 0.66 sa itaas hanggang -0.63 sa ibaba ang groups. Malawak at ganap na maayos ang ladder, dahil ginupit ang groups batay mismo sa score na iyon. Sa holdout, ang average ng parehong dalawang dulo ay 0.01 at 0.13. Lumalapat ang ladder. Ang holdout ang tanging bahagi ng pipeline na hindi na-optimize laban dito, kaya mahalagang gamitin ito nang maingat.

Mga depensang talagang gumagana

Isang holdout na gagamitin nang isang beses. Bawat pagtingin dito ay ginagawa itong training data. Ang walk-forward testing, kung saan gumugulong ang window at bawat score ay mula sa data pagkatapos ng fit, ang bersyong nananatiling maaasahan sa paulit-ulit na paggamit.

Isang multiple-testing adjustment. Ang deflated Sharpe ratio, na ipinakilala nina Bailey at López de Prado noong 2014, ay nagdi-discount sa observed Sharpe batay sa dami ng trials, haba ng sample, skewness ng returns, at kapal ng kanilang tails. Kapag pinakain ito ng tapat na trial count, ang headline Sharpe mula sa search na may sampung-libong expression ay madalas nauuwi sa wala.

Isang audit trail para sa bawat sinubukang expression, kabilang ang mga itinapon. Ito ang pinakamahalagang bahagi, at ito ang dahilan kung bakit kapansin-pansin ang salitang “auditable” sa paglalarawan ng isang factor-research project. Kailangan ng deflation ang trial count. Kapag winners lamang ang nilo-log ng pipeline, winawasak nito ang input para sa sarili nitong correction. Kasama sa bilang na iyon ang mga discarded draft, inabandunang parameter sweep, sariling pag-restart ng researcher, at bawat naunang bersyon ng scoring code.

Cost at look-ahead bias checks bago paniwalaan ang score. Ang factor na niraranggo gamit ang fundamentals field na may petsa kung kailan ito ni-load ng vendor, sa halip na petsa kung kailan ito maaaring makita ng market, ay maaaring magpakita ng magandang backtest ngunit masamang trading result.

Pagbasa sa salitang “auditable”

Halos bawat linggo ay may mga bagong repository sa larangang ito, at ang project na may ilang dosenang stars ay prototype, hindi track record. Mas mabilis ding gumalaw ang star count kaysa sa code. Kaya sinusuri ng page na ito ang pattern, hindi ang isang partikular na project. Narito ang unang dapat buksan sa anumang project na makita mo.

  • Nilo-log ba nito ang bawat candidate kasama ang expression at score nito, na may timestamp, o ang mga napanatili lamang?
  • Ipinapatupad ba ng harness ang holdout, o nakasalalay ito sa disiplina ng researcher?
  • May trial count bang nakalagay katabi ng bawat nirereport na score?
  • Para saang market ito ginawa? Ang library na tinune para sa China A-shares ay may daily price limits at restriction sa pagbebenta ng shares na binili sa parehong session. Hindi awtomatikong naililipat sa US equities ang behavior ng factor sa ilalim ng mga panuntunang iyon.
  • Maaari mo ba itong patakbuhin muli at ma-reproduce ang mga numero? I-pin ang eksaktong commit na binasa mo, dahil sa yugtong ito ay maaaring baguhin ng project ang scoring code nito sa pagitan ng dalawang weekend.

Hindi nito ginagawang walang silbi ang LLM sa factor research. Tunay na bottleneck ang pagbuo ng hypotheses, at mahusay dito ang mga model. Ang nagbabago ay kung saan napupunta ang burden: sa accounting kung ilang hypotheses ang ginamit. Bago ito humarap sa isang live order book, ang paper trading ang nagpapakita kung gaano kalayo ang pagitan ng backtest at aktuwal na fill.

LLM alpha factor FAQ

Makakahanap ba ang LLM ng alpha factors?

Maaari itong magmungkahi ng libo-libo, ngunit ang proposal ay hindi pa finding. Ginagawa ang claim sa scoring step, at ang score mula sa malawak na search ay may selection problem na hindi nakikita ng score mismo. Unahin ang holdout discipline at recorded trial count bago ang expression.

Ano ang deflated Sharpe ratio?

Isa itong correction na ginagawang probability ang observed Sharpe ratio: gaano kalamang na makagawa ng ganoong resulta ang isang search na ganoon kalaki kahit walang tunay na edge. Inilathala ito nina Bailey at López de Prado noong 2014. Ang pangunahing input nito ay ang bilang ng trials, na siyang eksaktong bilang na hindi maibibigay ng isang unaudited research loop.

Gaano karaming backtest ang sobra na?

Walang threshold. May adjustment lamang na kailangang ilapat. Magkaibang claim tungkol sa mundo ang isang backtest na may score na 1.0 at sampung-libong backtest na ang pinakamahusay na score ay 1.0. Umabot ang coin flips sa itaas sa 1.59 sa loob ng 240 trials kahit walang anumang information sa data.

Bakit humihina ang published factors pagkatapos mailathala?

Nasubaybayan sa academic research ang paghina ng published anomalies sa mga taong kasunod ng kanilang paglitaw. Isa sa mga ipinapakitang mekanismo ang crowding, at isa pa ang pag-overfit ng orihinal na resulta sa sarili nitong sample; pareho silang lumilikha ng parehong hugis sa chart. Tinutukoy ng efficient market hypothesis ang una, at ipinapakita ng mga trial sa itaas ang ikalawa.


Ang bawat panel dito ay isang stored query sa tunay na month-end prices, at bukas ang SQL sa ilalim nito. Kopyahin ang isa, dagdagan ang trial count, at panoorin kung paano tumataas ang pinakamagandang numero sa Strasmore terminal.

#llm#factor research#overfitting#multiple testing#quant