LLM alpha factors शोधू शकते का?
LLM एका तासात शंभर alpha factors लिहू शकते. 10 वर्षांच्या वास्तविक किमतींवर 240 coin flip factors ची कामगिरी आणि टिकून राहिलेल्यांची चाचणी कशी करावी, ते जाणून घ्या.
LLM दिवसभर alpha factors प्रस्तावित करू शकतो. सक्षम मॉडेलला data dictionary आणि scoring harness दिले, तर ते दुपारच्या जेवणापूर्वी शंभर संभाव्य factor expressions लिहू शकते. पण त्यापेक्षा कठीण प्रश्न पुढे येतो: त्यांपैकी एखादा खरा आहे हे कसे कळणार, जेव्हा तो शोधच noise मधून winners तयार करणारे यंत्र आहे?
alpha factor म्हणजे काय?
Factor हा असा नियम आहे, जो प्रत्येक तारखेला प्रत्येक stock साठी market data चे एका संख्येत रूपांतर करतो. बारा महिन्यांतील price change हा एक factor आहे. Debt-to-equity ratio देखील factor आहे. एखाद्या factor नुसार stocks च्या universe ची ranking करून, वरचा भाग खरेदी करणे, खालचा भाग विकणे आणि ठरावीक वेळापत्रकानुसार rebalance करणे सुरू झाले की factor चे strategy मध्ये रूपांतर होते. साध्या market exposure मधून मिळणारा परतावा वजा केल्यानंतर उरलेला परतावा म्हणजे Alpha.
उमेदवारांचे मूल्यांकन Sharpe ratio ने केले जाते: सरासरी परतावा भागिले त्या परताव्याचे standard deviation, आणि नंतर वर्षाच्या प्रमाणात मोजले जाते. म्हणजे अस्थिरतेच्या प्रत्येक युनिटमागे मिळणारा परतावा. Live strategy मध्ये दीर्घकाळाचा Sharpe जवळपास 1 असणे समाधानकारक मानले जाते. त्यामुळे पुढच्या वेळी backtest मध्ये 3 असा Sharpe दिसला, तेव्हा हे लक्षात ठेवा.
LLM factor research प्रत्यक्षात कसे चालते
या क्षेत्रातील प्रत्येक प्रकल्प साधारणपणे हाच चक्राकार प्रकार वापरतो.
- मॉडेल अशा छोट्या भाषेत factor expressions लिहिते, जिचे मूल्यांकन harness करू शकतो.
- Backtester ठरावीक price आणि fundamentals इतिहासावर प्रत्येक expression ला score देतो.
- ठरावीक score threshold पेक्षा जास्त असलेले expressions ठेवले जातात. उरलेले टाकून दिले जातात.
- ठेवलेले expressions worked examples म्हणून मॉडेलच्या context मध्ये परत दिले जातात आणि चक्र पुन्हा सुरू होते.
बहु-एजंट trading systems ही कामे वेगवेगळ्या भूमिकांमध्ये विभागतात—एक भूमिका प्रस्ताव मांडते आणि दुसरी चाचणी घेते. ही पायाभूत रचना खरोखर उपयुक्त आहे. तसेच AI agent ला आवश्यक असलेली market data कौशल्ये माणसालाही आवश्यक असतात.
या चक्रात काहीही अप्रामाणिक नाही. Research करण्याचा एक मार्ग म्हणजे search. अडचण arithmetic मध्ये आहे. Step 2 काही मोजक्या वेळांपेक्षा जास्त चालवला की ती लगेच दिसते.
LLM alpha factor search winners का तयार करते
एक price history. हजारो स्वस्त hypotheses. प्रत्येक hypothesis ची त्याच मर्यादित sample विरुद्ध चाचणी होते आणि त्या sample मध्ये नशिबाचा मोठा वाटा असतो. पुरेसे नियम तपासले, तर काही नियम त्या नशिबाशी अगदी जवळून जुळतील. तुम्हाला कोणत्या प्रकारचे fit मिळाले हे score सांगू शकत नाही, कारण noise शी जुळणारा नियम आणि market शी जुळणारा नियम दोन्ही तोच आकडा दाखवतात.
ही null hypothesis 240 वेळा काढली आहे. खालील प्रत्येक “factor” हा coin flip आहे: ticker, महिना आणि trial number यांचा hash वापरून दर महिन्याला 40 मोठ्या US names चे दोन भाग केले जातात. Strategy एका भागात long आणि दुसऱ्या भागात short position ठेवते. त्यात कोणतीही माहिती नाही; ही रचना तशीच आहे. January 2016 ते June 2021 या कालावधीतील प्रत्यक्ष month-end returns वर score दिल्यावर 240 trials चे वितरण असे दिसते.
प्रत्येक आकड्यामागील अचूक 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)यातील spread हाच मुख्य मुद्दा आहे. त्या chart मधील काहीही भविष्यातील हालचाल predict करत नाही. तरीही 1 trials वरच्या band मध्ये (1.2 and above), म्हणजे search च्या 0.4% मध्ये, गेले आणि 1 खालच्या band मध्ये (below -1.2) गेले. एखाद्या संशोधकाने एक lucky trial चालवून थांबले, तर त्याच्याकडे chart आणि Sharpe ratio असतील; पण त्यांना discovery पासून वेगळे ओळखण्याचा कोणताही मार्ग नसेल. येथे returns month-end close ते पुढील month-end close अशा पद्धतीने मोजले आहेत; monthly returns कसे मोजले जातात यामध्ये ते arithmetic दिले आहे.
तुम्ही किती चाचण्या केल्या हे महत्त्वाचे आहे
स्वतंत्रपणे दिलेल्या backtest मध्ये त्याचा denominator नसतो. त्याच 240 trials कडे असा search म्हणून पाहा जो सतत विस्तारत आहे: प्रत्येक टप्प्यावर, आतापर्यंतच्या सर्व चाचण्यांच्या सरासरीच्या शेजारी board वरील सर्वोत्तम score दाखवला जातो.
प्रत्येक आकड्यामागील अचूक 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_triedRunning maximum फक्त वाढू शकतो आणि हाच सापळा आहे. पहिल्या तपासलेल्या rule ला 0.44 score मिळाला. 240 trials नंतर board वरील सर्वोत्तम score 1.59 झाला, तर सर्व trials ची सरासरी 0.01 राहिली. एकही rule सुधारला नसताना headline सुधारली. दहा हजार expressions चे मूल्यांकन करणारा harness येथे दाखवलेल्या चित्रापेक्षा ही curve खूप उजवीकडे नेतो आणि तो ज्या आकड्याची नोंद करतो तो त्या curve चा सर्वोच्च बिंदू असतो.
Holdout period winners वर काय परिणाम करते
यासाठी standard defense म्हणजे holdout: एका कालावधीवर score देणे आणि नंतर टिकून राहिलेल्या rules ना search ने कधीही न पाहिलेल्या पुढील कालावधीवर पुन्हा score देणे. Training window मधील सर्वोत्तम बारा coin flips घ्या आणि त्याच rules नंतरच्या पाच वर्षांवर, July 2021 ते June 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प्रत्येक bars ची जोडी एका rule ची आहे. डावीकडील bar हा report मध्ये स्थान मिळवून देणारा score आहे. उजवीकडील bar पुढील पाच वर्षांतील त्याच rule चा score आहे. पहिल्या क्रमांकाच्या trial ला training मध्ये 1.59 score मिळाला आणि नंतर -0.51; बाराव्या trial ला अनुक्रमे 0.74 आणि 0.49 मिळाले.
बारा rules हा स्वतःमध्ये लहान sample आहे. Training score नुसार सर्व 240 rules ना पाच गटांत विभागून प्रत्येक गटाचा holdout score सरासरीने मोजला, तर अधिक स्पष्ट चित्र मिळते.
प्रत्येक आकड्यामागील अचूक 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)Training मध्ये गटांचा score वरच्या गटातील 0.66 पासून खालच्या गटातील -0.63 पर्यंत असतो. ही रुंद आणि पूर्णपणे शिस्तबद्ध शिडी असणे निश्चित आहे, कारण गटांची विभागणी त्याच score नुसार केली आहे. Holdout मध्ये हेच दोन टोकांचे गट सरासरीने 0.01 आणि 0.13 देतात. शिडी सपाट होते. Holdout हा pipeline मधील असा एकमेव भाग आहे, ज्याच्यावर optimization केलेले नसते. त्यामुळे त्याचा वापर काळजीपूर्वक करणे महत्त्वाचे आहे.
प्रत्यक्षात काम करणारे बचावात्मक उपाय
एकदाच वापरलेला holdout. प्रत्येक वेळी त्याकडे पाहिल्यावर तो training data मध्ये रूपांतरित होतो. Walk-forward testing मध्ये window पुढे सरकते आणि प्रत्येक score fit नंतरच्या data वरून येतो. वारंवार वापरल्यानंतरही टिकणारी हीच पद्धत आहे.
Multiple-testing adjustment. Bailey आणि López de Prado यांनी 2014 मध्ये मांडलेला deflated Sharpe ratio, किती trials चालवले, sample किती लांब आहे, returns किती skewed आहेत आणि त्यांच्या tails किती जाड आहेत यानुसार observed Sharpe ला discount करतो. Trial count प्रामाणिकपणे दिल्यास, दहा हजार expressions च्या search मधून मिळालेला headline Sharpe अनेकदा जवळजवळ शून्यावर येतो.
टाकून दिलेल्या expressions सह तपासलेल्या प्रत्येक expression ची audit trail. हा सर्वांत महत्त्वाचा भाग आहे. म्हणून factor-research प्रकल्पाच्या वर्णनात “auditable” हा शब्द महत्त्वाचा ठरतो. Deflation साठी trial count आवश्यक असतो. फक्त winners नोंदवणाऱ्या pipeline ने स्वतःच्या correction साठी आवश्यक input नष्ट केलेला असतो. Discarded drafts, सोडून दिलेले parameter sweeps, संशोधकाने केलेले स्वतःचे restarts आणि scoring code च्या प्रत्येक आधीच्या version चा trial count मध्ये समावेश होतो.
Score वर विश्वास ठेवण्यापूर्वी cost आणि look-ahead bias तपासा. Vendor ने data load केलेली तारीख वापरणाऱ्या fundamentals field वर factor ची ranking केली, पण market ला तो data उपलब्ध झालेली तारीख वापरली नाही, तर backtest सुंदर दिसतो आणि प्रत्यक्ष trading खराब होते.
“auditable” हा शब्द कसा वाचावा
या क्षेत्रात नवीन repositories जवळजवळ प्रत्येक आठवड्यात दिसतात. काही डझन stars असलेला प्रकल्प track record नसून prototype असतो. Code पेक्षा star counts वेगाने बदलतात. त्यामुळे हे पान एखाद्या विशिष्ट प्रकल्पाऐवजी पद्धतीचे मूल्यांकन करते. तुमच्यासमोर आलेल्या कोणत्याही प्रकल्पात प्रथम या गोष्टी तपासा.
- प्रत्येक candidate चे expression आणि score timestamp सह नोंदवले जातात का, की फक्त ठेवलेले candidates?
- Holdout ची अंमलबजावणी harness करते का, की संशोधकाच्या self-discipline वर ती अवलंबून आहे?
- प्रत्येक reported score सोबत trial count दिला आहे का?
- हा प्रकल्प कोणत्या market साठी तयार केला आहे? China A-shares साठी tuning केलेल्या library मध्ये daily price limits आणि त्याच session मध्ये खरेदी केलेले shares विकण्यावरील निर्बंध असतात. त्या नियमांखाली factor चे वर्तन US equities मध्ये तसेच लागू होईलच असे नाही.
- तुम्ही ते पुन्हा चालवून आकडे reproduce करू शकता का? तुम्ही वाचलेला exact commit pin करा, कारण या टप्प्यातील प्रकल्प weekends दरम्यान scoring code पुन्हा लिहू शकतो.
यापैकी कोणतीही गोष्ट LLM ला factor research मध्ये निरुपयोगी ठरवत नाही. Hypotheses तयार करणे हा खरा bottleneck आहे आणि models त्यात चांगले असतात. बदल एवढाच होतो की जबाबदारी कुठे पडते: किती hypotheses वापरून संपवले याच्या हिशोबावर. Live order book मध्ये पोहोचण्यापूर्वी, paper trading मध्ये backtest आणि प्रत्यक्ष fill यांतील अंतर दिसते.
LLM alpha factor FAQ
LLM alpha factors शोधू शकतो का?
तो हजारोंच्या संख्येने प्रस्ताव देऊ शकतो. पण proposal म्हणजे finding नाही. दावा scoring step वर केला जातो. विस्तृत search मधून मिळालेल्या score मध्ये selection problem असते आणि score स्वतः ते ओळखू शकत नाही. Expression पेक्षा holdout discipline आणि नोंदवलेला trial count आधी तपासा.
Deflated Sharpe ratio म्हणजे काय?
Observed Sharpe ratio चे असे correction, जेवढ्या मोठ्या search मध्ये कोणताही वास्तविक edge नसताना तो Sharpe मिळण्याची शक्यता किती आहे हे मोजते. Bailey आणि López de Prado यांनी ते 2014 मध्ये प्रकाशित केले. त्याचा मुख्य input म्हणजे trials ची संख्या. Unaudited research loop हीच संख्या देऊ शकत नाही.
किती backtests खूप जास्त मानले जातात?
यासाठी कोणताही threshold नाही. फक्त adjustment लागू करणे आवश्यक आहे. 1.0 score देणारा एक backtest आणि सर्वोत्तम score 1.0 असलेले दहा हजार backtests हे जगाविषयी वेगवेगळे दावे आहेत. वरील coin flips नी कोणतीही वास्तविक माहिती नसताना 1.59 trials मध्ये 240 गाठले.
Publication नंतर published factors कमजोर का होतात?
Academic research ने published anomalies दिसल्यानंतरच्या वर्षांत त्यांचा decay नोंदवला आहे. Crowding हे त्यासाठी मांडलेले एक कारण आहे. स्वतःच्या sample वर overfit झालेला original result हे दुसरे कारण आहे. दोन्ही कारणे chart वर समान आकार दाखवतात. efficient market hypothesis पहिल्या कारणाची चौकट देते, तर वरील trials दुसरे कारण स्पष्ट करतात.
येथील प्रत्येक panel हा प्रत्यक्ष month-end prices वर चालवलेला stored query आहे आणि त्याखाली SQL खुला आहे. एक query copy करा, trial count वाढवा आणि Strasmore terminal वर सर्वोत्तम आकडा चढताना पाहा.