Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

LLM ఆల్ఫా ఫ్యాక్టర్లను కనుగొనగలదా?

LLM ఒక గంటలో వంద ఆల్ఫా ఫ్యాక్టర్లను రాయగలదు. పదేళ్ల వాస్తవ ధరలపై 240 యాదృచ్ఛిక ఫ్యాక్టర్లు ఎలా స్కోర్ చేశాయో, విజయవంతమైన వాటిని ఎలా పరీక్షించాలో తెలుసుకోండి.

LLM రోజంతా ఆల్ఫా ఫ్యాక్టర్లను ప్రతిపాదించగలదు. సామర్థ్యమున్న మోడల్‌కు డేటా డిక్షనరీ, స్కోరింగ్ హార్నెస్ ఇస్తే, భోజనానికి ముందే నమ్మదగినట్టుగా కనిపించే వంద ఫ్యాక్టర్ ఎక్స్‌ప్రెషన్లను రాస్తుంది. కానీ అసలు కఠినమైన ప్రశ్న ఇదే: శబ్దం నుంచి విజేతలను తయారు చేసే శోధనలో ఒకటి నిజమైనదో ఎలా తెలుసుకోవాలి?

ఆల్ఫా ఫ్యాక్టర్ అంటే ఏమిటి?

ఫ్యాక్టర్ అనేది ప్రతి తేదీన ప్రతి స్టాక్‌కు మార్కెట్ డేటాను ఒక సంఖ్యగా మార్చే నియమం. పన్నెండు నెలల ధర మార్పు ఒక ఫ్యాక్టర్. అప్పు-ఈక్విటీ నిష్పత్తి కూడా అంతే. ఒక యూనివర్స్‌ను ఆ ఫ్యాక్టర్ ఆధారంగా ర్యాంక్ చేసి, పై భాగాన్ని కొనుగోలు చేసి, దిగువ భాగాన్ని విక్రయించి, నిర్ణీత షెడ్యూల్ ప్రకారం రీబ్యాలెన్స్ చేస్తే ఫ్యాక్టర్ వ్యూహంగా మారుతుంది. సాధారణ మార్కెట్ ఎక్స్‌పోజర్‌ ద్వారా సహజంగా వచ్చిన రాబడిని తీసివేసిన తర్వాత మిగిలేది ఆల్ఫా.

అభ్యర్థులకు Sharpe ratioతో స్కోరు ఇస్తారు: సగటు రాబడిని ఆ రాబడి ప్రామాణిక విచలనంతో భాగించి, సంవత్సరానికి స్కేల్ చేస్తారు. ఇది అస్థిరత ప్రతి యూనిట్‌కు లభించే రాబడి. లైవ్ వ్యూహంలో దీర్ఘకాలిక Sharpe సుమారు 1 ఉంటే గౌరవప్రదమైనదే. తర్వాత ఏదైనా బ్యాక్‌టెస్ట్ 3 అని చూపించినప్పుడు ఈ విషయాన్ని గుర్తుంచుకోవాలి.

LLM ఫ్యాక్టర్ పరిశోధన వాస్తవంగా ఎలా పనిచేస్తుంది

ఈ రంగంలోని ప్రతి ప్రాజెక్ట్ దాదాపు ఇదే చక్రాన్ని అమలు చేస్తుంది.

  1. హార్నెస్ మూల్యాంకనం చేయగల చిన్న భాషలో మోడల్ ఫ్యాక్టర్ ఎక్స్‌ప్రెషన్లను రాస్తుంది.
  2. బ్యాక్‌టెస్టర్ ప్రతి ఎక్స్‌ప్రెషన్‌ను నిర్ణీత ధరలు, ఫండమెంటల్స్ చరిత్రపై స్కోర్ చేస్తుంది.
  3. నిర్ణీత పరిమితికి మించిన ఎక్స్‌ప్రెషన్లను ఉంచుతారు. మిగతావి తొలగిస్తారు.
  4. ఉంచిన ఎక్స్‌ప్రెషన్లు పనిచేసిన ఉదాహరణలుగా మోడల్ కాంటెక్స్ట్‌లోకి తిరిగి వెళ్తాయి. తర్వాత చక్రం మళ్లీ నడుస్తుంది.

బహుళ-ఏజెంట్ ట్రేడింగ్ వ్యవస్థలు ఈ పనులను వేర్వేరు పాత్రలకు విభజిస్తాయి. ఒకటి ప్రతిపాదిస్తుంది, మరొకటి పరీక్షిస్తుంది. ఈ మౌలిక నిర్మాణం నిజంగా ఉపయోగకరమే. అలాగే AI ఏజెంట్‌కు అవసరమైన మార్కెట్ డేటా నైపుణ్యాలు ఒక వ్యక్తికి అవసరమైనవే.

ఈ చక్రంలో మోసం ఏదీ లేదు. పరిశోధన ఎలా జరుగుతుందో శోధన కూడా అలానే జరుగుతుంది. సమస్య గణితంలో ఉంది. రెండో దశను కొన్ని సార్లకంటే ఎక్కువ నడిపిన క్షణమే అది కనిపిస్తుంది.

LLM ఆల్ఫా ఫ్యాక్టర్ శోధన విజేతలను ఎందుకు తయారు చేస్తుంది

ఒకే ధర చరిత్ర. వేలాది చవకైన ఊహాగానాలు. ప్రతి ఊహాగానాన్ని అదే పరిమిత నమూనాపై స్కోర్ చేస్తారు. ఆ నమూనాలో అదృష్టానికి పెద్ద పాత్ర ఉంటుంది. తగినన్ని నియమాలను పరీక్షిస్తే, కొన్ని అదృష్టంతో బాగా సరిపోతాయి. మీకు లభించిన సరిపోలిక ఏ రకమైనదో స్కోరు చెప్పదు. శబ్దంతో సరిపోయిన నియమం, మార్కెట్‌ను నిజంగా పట్టుకున్న నియమం రెండూ ఒకే సంఖ్యను చూపగలవు.

ఇక్కడ శూన్య పరికల్పనను 240 సార్లు గీసాం. కింద ఉన్న ప్రతి “ఫ్యాక్టర్” ఒక కాయిన్-ఫ్లిప్: టికర్, నెల, ట్రయల్ నంబర్‌ల హ్యాష్ ప్రతి నెల 40 పెద్ద US పేర్లను రెండు భాగాలుగా విభజిస్తుంది. వ్యూహం ఒక భాగాన్ని లాంగ్‌గా, మరొకదాన్ని షార్ట్‌గా ఉంచుతుంది. నిర్మాణం ప్రకారం అందులో ఎలాంటి సమాచారం లేదు. January 2016 నుంచి June 2021 వరకు వాస్తవ నెలాఖరు రాబడులపై స్కోర్ చేస్తే, 240 ట్రయల్స్ ఇలా కనిపిస్తాయి.

క్వెరీవాస్తవ ధరలపై 240 కాయిన్-ఫ్లిప్ కారకాలకు స్కోరు: వార్షికీకరించిన Sharpe, జనవరి 2016 నుండి జూన్ 2021 వరకు
ప్రతి సంఖ్య వెనుక ఉన్న ఖచ్చితమైన SQL
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

స్ప్రెడ్‌నే అసలు విషయం. ఆ చార్ట్‌లో ఏదీ ఏదీ అంచనా వేయదు. అయినా 1 ట్రయల్స్ పై బ్యాండ్‌లో (1.2 and above), శోధనలో 0.4%, దిగువ బ్యాండ్‌లో 1 (below -1.2) చేరాయి. ఒక పరిశోధకుడు అదృష్టవంతమైన ఒక్క ట్రయల్‌ను నడిపి ఆపేస్తే, అతని వద్ద చార్ట్, Sharpe ratio ఉంటాయి. కానీ అది నిజమైన కనుగొనికతో భిన్నమని చెప్పే మార్గం ఉండదు. ఇక్కడి రాబడులు నెలాఖరు ముగింపు నుంచి తదుపరి నెలాఖరు ముగింపు వరకు కొలిచినవి. నెలవారీ రాబడులను ఎలా కొలుస్తారో ఆ గణితాన్ని వివరిస్తుంది.

మీరు ప్రయత్నించిన వాటి సంఖ్యే ముఖ్యమైన సంఖ్య

ఒంటరిగా చూపించిన బ్యాక్‌టెస్ట్‌లో హారం కనిపించదు. అదే 240 ట్రయల్స్‌ను క్రమంగా విస్తరిస్తున్న శోధనగా చూడండి: ప్రతి దశలో ఇప్పటివరకు పరీక్షించిన వాటి సగటు పక్కన బోర్డుపై ఉన్న అత్యుత్తమ స్కోరు.

క్వెరీశోధన పరిమాణం పెరిగేకొద్దీ ఉత్తమ స్కోరు పెరుగుతుంది: నిర్వహించిన ట్రయల్స్ ఆధారంగా ఉత్తమ మరియు సగటు Sharpe
ప్రతి సంఖ్య వెనుక ఉన్న ఖచ్చితమైన SQL
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

రన్నింగ్ మ్యాక్సిమమ్ ఎప్పుడూ పెరగగలదే కానీ తగ్గదు. ఇదే అసలు ఉచ్చు. మొదట పరీక్షించిన నియమం 0.44 స్కోర్ చేసింది. 240 ట్రయల్స్ తర్వాత బోర్డుపై అత్యుత్తమ స్కోరు 1.59గా ఉంది. వాటన్నింటి సగటు మాత్రం 0.01. ఒక్క నియమం కూడా మెరుగుపడకుండానే హెడ్‌లైన్ మెరుగుపడింది. పది వేల ఎక్స్‌ప్రెషన్లను మూల్యాంకనం చేసే హార్నెస్ ఇక్కడ గీసిన దానికంటే చాలా కుడివైపు ఈ వక్రాన్ని కొనసాగిస్తుంది. అది నివేదించే సంఖ్య ఆ వక్రం పైభాగమే.

హోల్డ్‌అవుట్ కాలం విజేతలకు ఏమి చేస్తుంది

సాధారణ రక్షణ హోల్డ్‌అవుట్: ఒక కాలంలో స్కోర్ చేసి, ఆ శోధన ఎప్పుడూ చూడని తర్వాతి కాలంలో మిగిలినవారిని మళ్లీ స్కోర్ చేయడం. శిక్షణ కాలంలో అత్యుత్తమమైన పన్నెండు కాయిన్-ఫ్లిప్‌లను తీసుకుని, July 2021 నుంచి June 2026 వరకు వచ్చిన ఐదు సంవత్సరాల్లో అదే నియమాలను నడపండి.

క్వెరీశిక్షణలో ఉత్తమమైన పన్నెండు ట్రయల్స్‌ను ఉపయోగించని ఐదు సంవత్సరాలపై మళ్లీ స్కోర్ చేయడం (జూలై 2021 నుండి జూన్ 2026 వరకు)
ప్రతి సంఖ్య వెనుక ఉన్న ఖచ్చితమైన SQL
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

ప్రతి బార్ జత ఒక నియమాన్ని సూచిస్తుంది. ఎడమ బార్ నివేదికలో స్థానం సంపాదించిన స్కోరు. కుడి బార్ తర్వాతి ఐదు సంవత్సరాల్లో అదే నియమం సాధించిన స్కోరు. శిక్షణలో అగ్రస్థానంలోని ట్రయల్ 1.59 స్కోర్ చేసింది; తర్వాత -0.51. పన్నెండవ ట్రయల్ 0.74 స్కోర్ చేసి, ఆ తర్వాత 0.49 సాధించింది.

పన్నెండు నియమాలు కూడా చిన్న నమూనానే. శిక్షణ స్కోరు ఆధారంగా మొత్తం 240 నియమాలను ఐదో వంతులుగా క్రమబద్ధీకరించి, ప్రతి ఐదో వంతు హోల్డ్‌అవుట్ స్కోరును సగటు చేస్తే మరింత స్పష్టమైన చిత్రం వస్తుంది.

క్వెరీశిక్షణ ర్యాంక్ వర్సెస్ హోల్డ్‌అవుట్ ఫలితం: 240 ట్రయల్స్‌ను ఐదో వంతులుగా విభజించడం
ప్రతి సంఖ్య వెనుక ఉన్న ఖచ్చితమైన SQL
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

శిక్షణలో సమూహాలు పైభాగంలోని 0.66 నుంచి దిగువ భాగంలోని -0.63 వరకు సాగుతాయి. ఈ క్రమం పూర్తిగా సహజమే, ఎందుకంటే సమూహాలను అదే స్కోరు ఆధారంగా విభజించారు. హోల్డ్‌అవుట్‌లో అదే రెండు చివరల సగతులు 0.01, 0.13. మెట్ల ఆకారం చదునవుతుంది. హోల్డ్‌అవుట్ మాత్రమే పైప్‌లైన్ ఆప్టిమైజ్ చేయని భాగం. అందుకే దానిని జాగ్రత్తగా ఖర్చు చేయాలి.

నిజంగా పనిచేసే రక్షణలు

ఒక్కసారి మాత్రమే ఉపయోగించే హోల్డ్‌అవుట్. దానిని ప్రతి సారి చూడటం ద్వారా అది శిక్షణ డేటాగా మారుతుంది. వాక్-ఫార్వర్డ్ టెస్టింగ్‌లో విండో ముందుకు కదులుతుంది. ప్రతి స్కోరు ఫిట్ చేసిన కాలం తర్వాతి డేటా నుంచి వస్తుంది. పునరావృత వినియోగాన్ని తట్టుకునేది ఇదే పద్ధతి.

మల్టిపుల్-టెస్టింగ్ సవరణ. Bailey మరియు López de Prado 2014లో ప్రవేశపెట్టిన deflated Sharpe ratio, ఎన్ని ట్రయల్స్ నడిచాయో, నమూనా ఎంత దీర్ఘమో, రాబడులు ఎంత వక్రంగా ఉన్నాయో, వాటి టెయిల్స్ ఎంత మందంగా ఉన్నాయో పరిగణించి గమనించిన Sharpe‌ను తగ్గిస్తుంది. నిజమైన ట్రయల్ సంఖ్యను ఇస్తే, పది వేల ఎక్స్‌ప్రెషన్ల శోధన నుంచి వచ్చిన హెడ్‌లైన్ Sharpe తరచుగా శూన్యానికి దగ్గరగా పడిపోతుంది.

తొలగించిన వాటితో సహా పరీక్షించిన ప్రతి ఎక్స్‌ప్రెషన్‌కు ఆడిట్ ట్రెయిల్. ఇదే అత్యంత కీలకం. అందుకే ఫ్యాక్టర్-రీసెర్చ్ ప్రాజెక్ట్ వివరణలో “ఆడిటబుల్” అనే పదం ముఖ్యమైనది. తగ్గింపు లెక్కకు ట్రయల్ సంఖ్య అవసరం. విజేతలను మాత్రమే నమోదు చేసే పైప్‌లైన్, తన సొంత సవరణకు అవసరమైన ఇన్‌పుట్‌ను నాశనం చేస్తుంది. తొలగించిన డ్రాఫ్ట్‌లు, వదిలేసిన పారామీటర్ స్వీప్‌లు, పరిశోధకుడు స్వయంగా మళ్లీ ప్రారంభించిన ప్రయత్నాలు, స్కోరింగ్ కోడ్‌లోని ప్రతి పాత వెర్షన్—ఇవన్నీ ఆ సంఖ్యలో లెక్కించాలి.

స్కోరును నమ్మే ముందు ఖర్చు, లుక్-ఎహెడ్ బయాస్ తనిఖీలు. మార్కెట్‌కు సమాచారం కనిపించిన తేదీకి బదులుగా విక్రేత దాన్ని లోడ్ చేసిన తేదీ ముద్రించిన ఫండమెంటల్స్ ఫీల్డ్‌పై ర్యాంక్ చేసిన ఫ్యాక్టర్ బ్యాక్‌టెస్ట్‌లో అద్భుతంగా కనిపించవచ్చు. కానీ ట్రేడింగ్‌లో చెడుగా పనిచేస్తుంది.

“ఆడిటబుల్” అనే పదాన్ని ఎలా చదవాలి

ఈ రంగంలో కొత్త రిపాజిటరీలు దాదాపు ప్రతి వారం కనిపిస్తాయి. కొన్ని డజన్ల స్టార్లు ఉన్న ప్రాజెక్ట్ ట్రాక్ రికార్డ్ కాదు; అది ప్రోటోటైప్. కోడ్ కంటే స్టార్ కౌంట్ వేగంగా మారుతుంది. అందుకే ఈ పేజీ ఏకైక ప్రాజెక్ట్‌కు బదులుగా నమూనాను పరిశీలిస్తుంది. మీ ముందుకు వచ్చిన ప్రాజెక్ట్‌లో మొదట వీటిని తెరవండి.

  • ప్రతి అభ్యర్థిని దాని ఎక్స్‌ప్రెషన్, స్కోరు, టైమ్‌స్టాంప్‌తో నమోదు చేస్తుందా? లేక ఉంచినవాటినేనా?
  • హోల్డ్‌అవుట్‌ను హార్నెస్ అమలు చేస్తుందా? లేక పరిశోధకుడి స్వీయ నియంత్రణపైనే ఆధారపడుతుందా?
  • నివేదించిన ప్రతి స్కోరు పక్కన ట్రయల్ సంఖ్య ఉందా?
  • ఇది ఏ మార్కెట్ కోసం రూపొందించబడింది? China A-shares కోసం ట్యూన్ చేసిన లైబ్రరీకి రోజువారీ ధర పరిమితులు, అదే సెషన్‌లో కొనుగోలు చేసిన షేర్లను విక్రయించలేని పరిమితి వారసత్వంగా వస్తాయి. ఆ నియమాల కింద ఫ్యాక్టర్ ప్రవర్తన US ఈక్విటీలకు వర్తించదు.
  • మీరు దీన్ని మళ్లీ నడిపి సంఖ్యలను పునరుత్పత్తి చేయగలరా? మీరు చదివిన ఖచ్చితమైన commit‌ను స్థిరపరచండి. ఈ దశలోని ప్రాజెక్ట్ వారాంతాల మధ్యే స్కోరింగ్ కోడ్‌ను మార్చవచ్చు.

ఇవేవీ ఫ్యాక్టర్ పరిశోధనలో LLMను పనికిరానిదిగా చేయవు. పరికల్పనలను రూపొందించడం నిజమైన అడ్డంకి. మోడళ్లు అందులో మంచివి. మారేది బాధ్యత ఎక్కడ పడుతుందో అన్నది: ఎన్ని పరికల్పనలను ఖర్చు చేశారో లెక్కించడంపై. లైవ్ ఆర్డర్ బుక్‌ను తాకే ముందు, పేపర్ ట్రేడింగ్ బ్యాక్‌టెస్ట్ మరియు వాస్తవ అమలు మధ్య దూరాన్ని చూపిస్తుంది.

LLM ఆల్ఫా ఫ్యాక్టర్ FAQ

LLM ఆల్ఫా ఫ్యాక్టర్లను కనుగొనగలదా?

వెయ్యుల కొద్దీ వాటిని ప్రతిపాదించగలదు. కానీ ప్రతిపాదన కనుగొనిక కాదు. వాదన స్కోరింగ్ దశలో మొదలవుతుంది. విస్తృత శోధన నుంచి వచ్చిన స్కోరులో ఎంపిక సమస్య ఉంటుంది. ఆ సమస్యను స్కోరు స్వయంగా గుర్తించదు. ఎక్స్‌ప్రెషన్ కంటే ముందు హోల్డ్‌అవుట్ క్రమశిక్షణ, నమోదు చేసిన ట్రయల్ సంఖ్యను పరిశీలించండి.

Deflated Sharpe ratio అంటే ఏమిటి?

నిజమైన అంచు లేనప్పటికీ, అదే పరిమాణంలోని శోధన ఆ Sharpe ratioను పొందే సంభావ్యతను పరిగణనలోకి తీసుకుని గమనించిన Sharpe ratioను సవరించే పద్ధతి. Bailey మరియు López de Prado దీన్ని 2014లో ప్రచురించారు. దాని ప్రధాన ఇన్‌పుట్ ట్రయల్స్ సంఖ్య. ఆడిట్ లేని పరిశోధనా చక్రం అందించలేనిది ఇదే.

ఎన్ని బ్యాక్‌టెస్టులు చాలా ఎక్కువ?

నిర్దిష్ట పరిమితి లేదు. వర్తించాల్సింది సవరణ మాత్రమే. 1.0 స్కోర్ చేసిన ఒక బ్యాక్‌టెస్ట్, అత్యుత్తమ స్కోరు 1.0గా ఉన్న పది వేల బ్యాక్‌టెస్టులు ప్రపంచం గురించి వేర్వేరు వాదనలు. పై కాయిన్-ఫ్లిప్‌లు డేటాలో ఏమీ లేకుండానే 1.59ను 240 ట్రయల్స్‌లో సాధించాయి.

ప్రచురణ తర్వాత ప్రచురించిన ఫ్యాక్టర్లు ఎందుకు బలహీనపడతాయి?

ప్రచురించిన అనామలీలు బయటకు వచ్చిన తర్వాతి సంవత్సరాల్లో ఎలా క్షీణిస్తాయో అకాడమిక్ పరిశోధనలు నమోదు చేశాయి. మార్కెట్‌లో అధిక సమూహీకరణ ఒక కారణంగా చెప్పబడుతుంది. అసలు ఫలితం తన నమూనాకే అతిగా సరిపోవడం మరో కారణం. రెండూ చార్ట్‌లో ఒకే ఆకారాన్ని చూపుతాయి. సమర్థవంతమైన మార్కెట్ పరికల్పన మొదటి కారణాన్ని వివరిస్తుంది. పై ట్రయల్స్ రెండో కారణాన్ని చూపిస్తాయి.


ఇక్కడి ప్రతి ప్యానెల్ వాస్తవ నెలాఖరు ధరలపై నిల్వ చేసిన query. దాని కింద SQL పూర్తిగా అందుబాటులో ఉంది. ఒకదాన్ని కాపీ చేసి, ట్రయల్ సంఖ్యను పెంచండి. Strasmore terminalలో అత్యుత్తమ సంఖ్య ఎలా పెరుగుతుందో గమనించండి.

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