Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor ·

Bolehkah LLM Menemui Faktor Alpha?

LLM boleh menulis seratus faktor alpha dalam sejam. Lihat prestasi 240 faktor lambungan syiling pada sepuluh tahun harga sebenar dan cara menguji faktor yang bertahan.

Sebuah LLM boleh mencadangkan faktor alpha sepanjang hari. Berikan model yang berkebolehan sebuah kamus data dan rangka kerja pemarkahan, lalu model itu akan menulis seratus ungkapan faktor yang munasabah sebelum waktu makan tengah hari. Persoalan yang lebih sukar ialah: bagaimana seseorang boleh tahu sama ada salah satu daripadanya benar-benar berkesan, sedangkan carian yang menghasilkannya ialah mesin untuk menghasilkan pemenang daripada hingar?

Apakah faktor alpha?

Faktor ialah peraturan yang menukarkan data pasaran kepada satu nombor bagi setiap saham pada setiap tarikh. Perubahan harga selama dua belas bulan ialah satu faktor. Begitu juga nisbah hutang kepada ekuiti. Faktor menjadi strategi apabila anda menyusun sesuatu universe mengikut faktor itu, membeli kelompok teratas, menjual kelompok terbawah dan mengimbangi semula portfolio mengikut jadual. Alpha ialah pulangan yang tinggal selepas menolak pulangan yang akan diberikan oleh pendedahan pasaran biasa.

Calon dinilai menggunakan nisbah Sharpe: pulangan purata dibahagikan dengan sisihan piawai pulangan tersebut, kemudian disetahunkan. Ia mengukur pulangan bagi setiap unit turun naik. Nisbah Sharpe jangka panjang sekitar 1 bagi strategi langsung adalah munasabah. Perkara ini wajar diingati apabila backtest seterusnya melaporkan angka 3.

Bagaimana penyelidikan faktor oleh LLM sebenarnya berfungsi

Setiap projek dalam bidang ini menjalankan variasi gelung yang sama.

  1. Model menulis ungkapan faktor dalam bahasa kecil yang boleh dinilai oleh rangka kerja tersebut.
  2. Backtester menilai setiap ungkapan berdasarkan sejarah harga dan asas yang tetap.
  3. Ungkapan yang melepasi ambang skor dikekalkan. Yang lain dibuang.
  4. Ungkapan yang dikekalkan dimasukkan semula ke dalam konteks model sebagai contoh yang telah berfungsi, kemudian gelung dijalankan semula.

Sistem dagangan berbilang ejen membahagikan tugasan tersebut kepada peranan yang berasingan: satu mencadangkan dan satu lagi menguji. Infrastruktur ini sememangnya berguna, dan kemahiran data pasaran yang diperlukan oleh ejen AI adalah sama seperti yang diperlukan oleh manusia.

Tiada apa-apa yang tidak jujur dalam gelung ini. Carian ialah cara penyelidikan dijalankan. Masalahnya ialah aritmetik, dan ia muncul sebaik sahaja langkah 2 dijalankan lebih daripada beberapa kali.

Mengapa carian faktor alpha oleh LLM menghasilkan pemenang secara palsu

Satu sejarah harga. Beribu-ribu hipotesis murah. Setiap hipotesis dinilai terhadap sampel terhingga yang sama, dan sampel itu mengandungi banyak unsur nasib. Uji secukupnya banyak peraturan, maka sebahagiannya akan terpadan rapat dengan nasib tersebut. Skor tidak dapat memberitahu jenis padanan yang diperoleh, kerana peraturan yang memadankan hingar dan peraturan yang memadankan pasaran akan menghasilkan nombor yang sama.

Berikut ialah hipotesis nol yang diambil sebanyak 240 kali. Setiap “faktor” di bawah ialah lambungan syiling: hash ticker, bulan dan nombor percubaan membahagikan 40 nama besar AS kepada dua bahagian setiap bulan. Strategi ini mengambil posisi long pada satu bahagian dan short pada bahagian yang lain. Mengikut binaannya, tiada maklumat dalam faktor tersebut. Apabila dinilai menggunakan pulangan sebenar pada akhir bulan dari Januari 2016 hingga Jun 2021, 240 percubaan itu menghasilkan taburan berikut.

Pertanyaan240 faktor lambungan syiling dinilai berdasarkan harga sebenar: Sharpe tahunan, Jan 2016 hingga Jun 2021
SQL tepat di sebalik setiap nombor
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

Jurang itu ialah perkara utama. Tiada apa-apa pada carta tersebut yang meramalkan apa-apa, namun 1 percubaan berada dalam kelompok teratas (1.2 and above), 0.4% daripada keseluruhan carian, dan 1 berada dalam kelompok terbawah (below -1.2). Penyelidik yang menjalankan satu percubaan bertuah lalu berhenti akan memiliki carta dan nisbah Sharpe, tanpa cara membezakan kedua-duanya daripada satu penemuan. Pulangan di sini dikira dari penutupan akhir bulan ke penutupan akhir bulan; cara pulangan bulanan diukur menerangkan pengiraan tersebut.

Nombor yang penting ialah jumlah percubaan

Laporan backtest secara bersendirian tidak mempunyai penyebut. Baca 240 percubaan yang sama sebagai satu carian yang terus diperluas: pada setiap langkah, skor terbaik pada papan dibandingkan dengan purata semua percubaan yang telah dilakukan setakat itu.

PertanyaanSkor terbaik meningkat mengikut saiz carian: Sharpe terbaik dan purata mengikut percubaan dijalankan
SQL tepat di sebalik setiap nombor
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

Maksimum berjalan hanya boleh meningkat, dan itulah perangkapnya. Peraturan pertama yang diuji mendapat skor 0.44. Selepas 240 percubaan, skor terbaik pada papan ialah 1.59, manakala purata keseluruhannya ialah 0.01. Tajuk utama bertambah baik tanpa satu pun peraturan menjadi lebih baik. Rangka kerja yang menilai sepuluh ribu ungkapan sedang melanjutkan lengkung ini jauh ke kanan daripada apa yang dipaparkan di sini, dan nombor yang dilaporkannya ialah titik paling tinggi pada lengkung tersebut.

Kesan tempoh yang tidak digunakan untuk pemenang

Pertahanan standard ialah set data simpanan: nilai satu tempoh, kemudian nilai semula calon yang terselamat pada tempoh kemudian yang tidak pernah disentuh oleh carian. Ambil dua belas lambungan syiling terbaik daripada tempoh latihan dan jalankan peraturan yang sama sepanjang lima tahun berikutnya, dari Julai 2021 hingga Jun 2026.

PertanyaanDua belas percubaan terbaik dalam latihan, dinilai semula pada lima tahun yang tidak disentuh (Jul 2021 hingga Jun 2026)
SQL tepat di sebalik setiap nombor
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

Setiap pasangan bar ialah satu peraturan. Bar kiri ialah skor yang memberikannya tempat dalam laporan. Bar kanan ialah skor peraturan yang sama sepanjang lima tahun berikutnya. Percubaan yang menduduki tempat teratas mendapat 1.59 dalam latihan dan -0.51 selepas itu; percubaan di tempat kedua belas mendapat 0.74 dan kemudian 0.49.

Dua belas peraturan juga merupakan sampel yang kecil. Susun semua 240 peraturan kepada lima kelompok mengikut skor latihan, kemudian puratakan skor set data simpanan bagi setiap kelompok. Hasilnya memberikan gambaran yang lebih jelas.

PertanyaanKedudukan latihan berbanding keputusan pegangan keluar: 240 percubaan dibahagikan kepada perlima
SQL tepat di sebalik setiap nombor
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

Dalam latihan, kumpulan tersebut bergerak daripada 0.66 di bahagian teratas kepada -0.63 di bahagian terbawah. Ia membentuk tangga yang lebar dan teratur sepenuhnya, kerana kumpulan itu memang dibentuk berdasarkan skor tersebut. Dalam set data simpanan, purata bagi kedua-dua hujung yang sama ialah 0.01 dan 0.13. Tangga itu menjadi rata. Set data simpanan ialah satu-satunya bahagian saluran kerja yang tidak dioptimumkan, dan itulah sebabnya ia wajar digunakan dengan cermat.

Pertahanan yang benar-benar berkesan

Set data simpanan yang digunakan sekali sahaja. Setiap kali anda melihatnya, data tersebut berubah menjadi data latihan. Ujian walk-forward, iaitu tetingkap yang bergerak dan setiap skor datang daripada data selepas proses pemadanan, ialah versi yang dapat bertahan apabila digunakan berulang kali.

Pelarasan untuk ujian berbilang. Nisbah Sharpe terlaras, yang diperkenalkan oleh Bailey dan López de Prado pada 2014, memberikan diskaun kepada Sharpe yang diperhatikan berdasarkan jumlah percubaan, tempoh sampel, kecondongan pulangan dan ketebalan ekornya. Masukkan jumlah percubaan yang jujur, dan Sharpe utama daripada carian sepuluh ribu ungkapan sering susut menjadi tiada apa-apa.

Jejak audit yang merangkumi setiap ungkapan yang diuji, termasuk yang dibuang. Inilah komponen asas, dan sebabnya perkataan “boleh diaudit” begitu penting dalam penerangan projek penyelidikan faktor. Pelarasan tersebut memerlukan jumlah percubaan. Saluran kerja yang hanya merekodkan pemenang telah memusnahkan input untuk pembetulannya sendiri. Draf yang dibuang, sapuan parameter yang ditinggalkan, percubaan semula oleh penyelidik dan setiap versi terdahulu kod pemarkahan semuanya dikira dalam jumlah itu.

Semakan kos dan bias pandang ke hadapan sebelum mempercayai skor. Faktor yang disusun berdasarkan medan asas yang dicap dengan tarikh vendor memuatkannya, bukannya tarikh medan itu boleh dilihat oleh pasaran, akan menghasilkan backtest yang sangat baik tetapi dagangan yang buruk.

Memahami perkataan “boleh diaudit”

Repositori baharu dalam bidang ini muncul hampir setiap minggu, dan projek dengan beberapa dozen bintang lebih menyerupai prototaip daripada rekod prestasi. Jumlah bintang juga berubah lebih pantas daripada kod, sebab itu halaman ini menilai coraknya, bukan mana-mana projek tertentu. Berikut ialah perkara yang perlu dibuka terlebih dahulu bagi mana-mana projek yang anda temui.

  • Adakah ia merekodkan setiap calon berserta ungkapan dan skornya, lengkap dengan cap masa, atau hanya calon yang dikekalkan?
  • Adakah set data simpanan dikuatkuasakan oleh rangka kerja, atau bergantung pada disiplin diri penyelidik?
  • Adakah setiap skor yang dilaporkan disertakan dengan jumlah percubaan?
  • Untuk pasaran manakah ia dibangunkan? Pustaka yang ditala untuk saham A China mewarisi had harga harian dan larangan menjual saham yang dibeli dalam sesi yang sama. Tingkah laku faktor di bawah peraturan tersebut tidak semestinya terpakai pada ekuiti AS.
  • Bolehkah anda menjalankannya semula dan menghasilkan nombor yang sama? Simpan commit tepat yang anda baca, kerana projek pada tahap ini boleh menulis semula kod pemarkahannya antara hujung minggu.

Tiada satu pun perkara ini menjadikan LLM tidak berguna dalam penyelidikan faktor. Penjanaan hipotesis ialah hambatan sebenar, dan model mahir melakukannya. Perubahannya ialah lokasi beban: ia beralih kepada perakaunan tentang jumlah hipotesis yang telah digunakan. Sebelum mana-mana strategi bertemu buku pesanan langsung, dagangan kertas ialah tempat perbezaan antara backtest dan pelaksanaan pesanan menjadi jelas.

Soalan lazim faktor alpha LLM

Bolehkah LLM mencari faktor alpha?

LLM boleh mencadangkannya dalam jumlah ribuan, tetapi cadangan bukanlah penemuan. Dakwaan tersebut dibuat pada langkah pemarkahan, dan skor daripada carian yang luas membawa masalah pemilihan yang tidak dapat dilihat oleh skor itu sendiri. Nilai disiplin set data simpanan dan jumlah percubaan yang direkodkan sebelum menilai ungkapan faktor.

Apakah nisbah Sharpe terlaras?

Ia ialah pembetulan yang menukarkan nisbah Sharpe yang diperhatikan kepada kebarangkalian bahawa carian sebesar itu akan menghasilkannya walaupun tiada kelebihan sebenar. Bailey dan López de Prado menerbitkannya pada 2014. Input utamanya ialah jumlah percubaan, iaitu angka yang tidak dapat dibekalkan oleh gelung penyelidikan tanpa audit.

Berapa banyak backtest yang terlalu banyak?

Tiada ambang tertentu. Yang diperlukan ialah pelarasan. Satu backtest dengan skor 1.0 dan sepuluh ribu backtest yang skor terbaiknya 1.0 merupakan dua dakwaan yang berbeza tentang dunia. Lambungan syiling di atas mencapai 1.59 dalam 240 percubaan walaupun tiada maklumat langsung dalam data.

Mengapa faktor yang diterbitkan menjadi lemah selepas diterbitkan?

Penyelidikan akademik telah menjejaki kemerosotan anomali yang diterbitkan sepanjang tahun-tahun selepas kemunculannya. Kesesakan posisi ialah salah satu mekanisme yang dicadangkan, manakala keputusan asal yang terlebih padan dengan sampelnya sendiri ialah satu lagi. Kedua-duanya menghasilkan bentuk carta yang sama. Hipotesis pasaran cekap menerangkan mekanisme pertama, manakala percubaan di atas menunjukkan mekanisme kedua.


Setiap panel di sini ialah pertanyaan tersimpan menggunakan harga sebenar pada akhir bulan, dengan SQL yang tersedia di bawahnya. Salin satu, tingkatkan jumlah percubaan dan lihat nombor terbaik meningkat pada terminal Strasmore.

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