[TOC]

Ada banyak laporan penelitian tentang model multi-faktor pasar saham, dengan teori dan praktik yang kaya. Pasar mata uang digital cukup untuk penelitian faktor, terlepas dari jumlah mata uang, total nilai pasar, volume transaksi, pasar derivatif, dll. Artikel ini terutama ditujukan untuk pemula strategi kuantitatif dan tidak akan melibatkan prinsip matematika yang rumit dan analisis statistik. Mengambil pasar berjangka sebagai sumber data, kerangka kerja penelitian faktor sederhana dibangun untuk memfasilitasi evaluasi indikator faktor.
Faktor dapat dilihat sebagai indikator dan dapat ditulis sebagai ekspresi. Faktor berubah secara terus-menerus dan mencerminkan informasi pengembalian di masa mendatang. Biasanya, faktor mewakili logika investasi.
Misalnya, faktor harga penutupan didasarkan pada asumsi bahwa harga saham dapat memprediksi keuntungan di masa mendatang. Semakin tinggi harga saham, semakin tinggi keuntungan di masa mendatang (atau semakin rendah keuntungannya). Membangun portofolio berdasarkan faktor ini sebenarnya adalah sebuah investasi. model/strategi rotasi posisi secara berkala untuk membeli saham berharga tinggi. Secara umum, faktor-faktor yang secara konsisten dapat menghasilkan keuntungan berlebih sering disebut Alpha. Misalnya, faktor kapitalisasi pasar dan faktor momentum telah diverifikasi oleh akademisi dan komunitas investasi sebagai faktor yang efektif.
Baik itu pasar saham maupun pasar mata uang digital, semuanya merupakan sistem yang kompleks. Tidak ada faktor yang dapat sepenuhnya memprediksi keuntungan di masa mendatang, tetapi masih memiliki tingkat prediktabilitas tertentu. Alpha yang efektif (model investasi) secara bertahap menjadi tidak efektif seiring bertambahnya dana yang diinvestasikan. Namun proses ini akan menghasilkan model-model lain di pasar, yang melahirkan alpha-alpha baru. Faktor kapitalisasi pasar pernah menjadi strategi yang sangat efektif di pasar saham A. Cukup beli 10 saham dengan kapitalisasi pasar terendah dan sesuaikan sekali sehari. Uji ulang sepuluh tahun dari tahun 2007 akan menghasilkan lebih dari 400 kali pengembalian, jauh lebih tinggi. melampaui pasar keseluruhan. Namun, pasar saham blue-chip pada tahun 2017 mencerminkan ketidakefektifan faktor kapitalisasi pasar kecil, sementara faktor nilai malah menjadi populer. Oleh karena itu, perlu untuk terus menyeimbangkan dan bereksperimen antara verifikasi dan penggunaan alfa.
Faktor-faktor yang kita cari adalah dasar untuk membangun strategi. Strategi yang lebih baik dapat dibangun dengan menggabungkan beberapa faktor efektif yang tidak terkait.
import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline
Sampai saat ini, data K-line per jam dari kontrak berjangka abadi Binance USDT sejak awal tahun 2022 hingga saat ini telah melampaui 150 mata uang. Seperti disebutkan sebelumnya, model faktor adalah model pemilihan mata uang yang menargetkan semua mata uang, bukan hanya mata uang tertentu. Data K-line meliputi data seperti harga pembukaan tertinggi dan harga penutupan terendah, volume perdagangan, jumlah transaksi, volume pembelian aktif, dan lain sebagainya. Data-data tersebut tentu saja bukan merupakan sumber dari semua faktor seperti indeks saham AS, ekspektasi kenaikan suku bunga, dan lain sebagainya. , profitabilitas, data on-chain, perhatian Media sosial, dll. Sumber data yang kurang populer mungkin juga mengungkapkan alpha yang efektif, tetapi data volume dan harga dasar juga memadai.
## 当前交易对
Info = requests.get('https://fapi.binance.com/fapi/v1/exchangeInfo')
symbols = [s['symbol'] for s in Info.json()['symbols']]
symbols = list(filter(lambda x: x[-4:] == 'USDT', [s.split('_')[0] for s in symbols]))
print(symbols)
Out:
['BTCUSDT', 'ETHUSDT', 'BCHUSDT', 'XRPUSDT', 'EOSUSDT', 'LTCUSDT', 'TRXUSDT', 'ETCUSDT', 'LINKUSDT',
'XLMUSDT', 'ADAUSDT', 'XMRUSDT', 'DASHUSDT', 'ZECUSDT', 'XTZUSDT', 'BNBUSDT', 'ATOMUSDT', 'ONTUSDT',
'IOTAUSDT', 'BATUSDT', 'VETUSDT', 'NEOUSDT', 'QTUMUSDT', 'IOSTUSDT', 'THETAUSDT', 'ALGOUSDT', 'ZILUSDT',
'KNCUSDT', 'ZRXUSDT', 'COMPUSDT', 'OMGUSDT', 'DOGEUSDT', 'SXPUSDT', 'KAVAUSDT', 'BANDUSDT', 'RLCUSDT',
'WAVESUSDT', 'MKRUSDT', 'SNXUSDT', 'DOTUSDT', 'DEFIUSDT', 'YFIUSDT', 'BALUSDT', 'CRVUSDT', 'TRBUSDT',
'RUNEUSDT', 'SUSHIUSDT', 'SRMUSDT', 'EGLDUSDT', 'SOLUSDT', 'ICXUSDT', 'STORJUSDT', 'BLZUSDT', 'UNIUSDT',
'AVAXUSDT', 'FTMUSDT', 'HNTUSDT', 'ENJUSDT', 'FLMUSDT', 'TOMOUSDT', 'RENUSDT', 'KSMUSDT', 'NEARUSDT',
'AAVEUSDT', 'FILUSDT', 'RSRUSDT', 'LRCUSDT', 'MATICUSDT', 'OCEANUSDT', 'CVCUSDT', 'BELUSDT', 'CTKUSDT',
'AXSUSDT', 'ALPHAUSDT', 'ZENUSDT', 'SKLUSDT', 'GRTUSDT', '1INCHUSDT', 'CHZUSDT', 'SANDUSDT', 'ANKRUSDT',
'BTSUSDT', 'LITUSDT', 'UNFIUSDT', 'REEFUSDT', 'RVNUSDT', 'SFPUSDT', 'XEMUSDT', 'BTCSTUSDT', 'COTIUSDT',
'CHRUSDT', 'MANAUSDT', 'ALICEUSDT', 'HBARUSDT', 'ONEUSDT', 'LINAUSDT', 'STMXUSDT', 'DENTUSDT', 'CELRUSDT',
'HOTUSDT', 'MTLUSDT', 'OGNUSDT', 'NKNUSDT', 'SCUSDT', 'DGBUSDT', '1000SHIBUSDT', 'ICPUSDT', 'BAKEUSDT',
'GTCUSDT', 'BTCDOMUSDT', 'TLMUSDT', 'IOTXUSDT', 'AUDIOUSDT', 'RAYUSDT', 'C98USDT', 'MASKUSDT', 'ATAUSDT',
'DYDXUSDT', '1000XECUSDT', 'GALAUSDT', 'CELOUSDT', 'ARUSDT', 'KLAYUSDT', 'ARPAUSDT', 'CTSIUSDT', 'LPTUSDT',
'ENSUSDT', 'PEOPLEUSDT', 'ANTUSDT', 'ROSEUSDT', 'DUSKUSDT', 'FLOWUSDT', 'IMXUSDT', 'API3USDT', 'GMTUSDT',
'APEUSDT', 'BNXUSDT', 'WOOUSDT', 'FTTUSDT', 'JASMYUSDT', 'DARUSDT', 'GALUSDT', 'OPUSDT', 'BTCUSDT',
'ETHUSDT', 'INJUSDT', 'STGUSDT', 'FOOTBALLUSDT', 'SPELLUSDT', '1000LUNCUSDT', 'LUNA2USDT', 'LDOUSDT',
'CVXUSDT']
print(len(symbols))
Out:
153
#获取任意周期K线的函数
def GetKlines(symbol='BTCUSDT',start='2020-8-10',end='2021-8-10',period='1h',base='fapi',v = 'v1'):
Klines = []
start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000
end_time = min(int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000 + 8*60*60*1000,time.time()*1000)
intervel_map = {'m':60*1000,'h':60*60*1000,'d':24*60*60*1000}
while start_time < end_time:
mid_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
url = 'https://'+base+'.binance.com/'+base+'/'+v+'/klines?symbol=%s&interval=%s&startTime=%s&endTime=%s&limit=1000'%(symbol,period,start_time,mid_time)
res = requests.get(url)
res_list = res.json()
if type(res_list) == list and len(res_list) > 0:
start_time = res_list[-1][0]+int(period[:-1])*intervel_map[period[-1]]
Klines += res_list
if type(res_list) == list and len(res_list) == 0:
start_time = start_time+1000*int(period[:-1])*intervel_map[period[-1]]
if mid_time >= end_time:
break
df = pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float')
df.index = pd.to_datetime(df.time,unit='ms')
return df
start_date = '2022-1-1'
end_date = '2022-09-14'
period = '1h'
df_dict = {}
for symbol in symbols:
df_s = GetKlines(symbol=symbol,start=start_date,end=end_date,period=period,base='fapi',v='v1')
if not df_s.empty:
df_dict[symbol] = df_s
symbols = list(df_dict.keys())
print(df_s.columns)
Out:
Index(['time', 'open', 'high', 'low', 'close', 'amount', 'end_time', 'volume',
'count', 'buy_amount', 'buy_volume', 'null'],
dtype='object')
Kami awalnya mengekstrak data yang diinginkan dari data garis K: harga penutupan, harga pembukaan, volume perdagangan, jumlah transaksi, dan rasio pembelian aktif, dan menggunakan data ini sebagai dasar untuk memproses faktor-faktor yang diperlukan.
df_close = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
df_open = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
df_volume = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
df_buy_ratio = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
df_count = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq=period),columns=df_dict.keys())
for symbol in df_dict.keys():
df_s = df_dict[symbol]
df_close[symbol] = df_s.close
df_open[symbol] = df_s.open
df_volume[symbol] = df_s.volume
df_count[symbol] = df_s['count']
df_buy_ratio[symbol] = df_s.buy_amount/df_s.amount
df_close = df_close.dropna(how='all')
df_open = df_open.dropna(how='all')
df_volume = df_volume.dropna(how='all')
df_count = df_count.dropna(how='all')
df_buy_ratio = df_buy_ratio.dropna(how='all')
Melihat kinerja indeks pasar, dapat dikatakan cukup suram, dengan penurunan 60% sejak awal tahun.
df_norm = df_close/df_close.fillna(method='bfill').iloc[0] #归一化
df_norm.mean(axis=1).plot(figsize=(15,6),grid=True);
#最终指数收益图

Metode regresi Tingkat pengembalian periode berikutnya diambil sebagai variabel dependen, faktor yang akan diuji diambil sebagai variabel independen, dan koefisien yang diperoleh melalui regresi adalah tingkat pengembalian faktor tersebut. Setelah membuat persamaan regresi, biasanya kita mengacu pada nilai rata-rata absolut dari nilai koefisien t, proporsi urutan nilai absolut dari nilai koefisien t lebih besar dari 2, pengembalian faktor tahunan, volatilitas pengembalian faktor tahunan, rasio Sharpe dari pengembalian faktor dan parameter lainnya. Efektivitas dan volatilitas faktor. Anda dapat melakukan regresi beberapa faktor sekaligus, rujuk dokumentasi barra untuk detailnya.
IC, IR dan indikator lainnya IC adalah koefisien korelasi antara faktor dan tingkat pengembalian periode berikutnya. RANK_IC umumnya digunakan sekarang, yang merupakan koefisien korelasi antara peringkat faktor dan tingkat pengembalian saham periode berikutnya. IR secara umum adalah rata-rata urutan IC/deviasi standar urutan IC.
Regresi hierarkis Artikel ini akan menggunakan metode ini, yaitu mengurutkan faktor yang akan diuji, membagi mata uang ke dalam N kelompok untuk pengujian ulang kelompok, dan menggunakan periode tetap untuk menyesuaikan posisi. Apabila situasinya ideal, imbal hasil dari kelompok N mata uang akan menunjukkan monotonisitas yang baik, meningkat atau menurun secara monoton, dan kesenjangan imbal hasil antara setiap kelompok akan besar. Faktor-faktor tersebut tercermin dalam diskriminasi yang lebih baik. Jika kelompok pertama memiliki pengembalian tertinggi dan kelompok terakhir memiliki pengembalian terendah, maka ambil posisi long pada kelompok pertama dan short pada kelompok terakhir. Tingkat pengembalian akhir merupakan indikator referensi rasio Sharpe.
Berdasarkan faktor-faktor tersebut, mata uang yang dipilih dibagi menjadi 3 kelompok sesuai dengan urutan dari kecil ke besar. Setiap kelompok mata uang mencakup sekitar 1⁄3. Jika suatu faktor efektif, semakin kecil proporsi masing-masing kelompok, semakin tinggi menghasilkan, tetapi itu juga berarti Dana yang dialokasikan untuk setiap mata uang relatif besar. Jika posisi panjang dan pendek masing-masing memiliki leverage 1x, dan kelompok pertama dan terakhir masing-masing adalah 10 mata uang, maka masing-masing menyumbang 10%. Jika mata uang yang kenaikan short, Jika jumlah investasi meningkat 2 kali lipat, maka retracement akan menjadi 20%; dengan kata lain, jika jumlah grup 50, maka retracement akan menjadi 4%. Diversifikasi mata uang dapat mengurangi risiko angsa hitam. Ambil posisi long pada kelompok pertama (dengan nilai faktor terkecil) dan short pada kelompok ketiga. Jika semakin besar faktornya, semakin tinggi pengembaliannya, Anda dapat membalikkan posisi panjang dan pendek atau sekadar menjadikan faktornya negatif atau terbalik.
Kekuatan prediktif suatu faktor biasanya dapat dinilai secara kasar berdasarkan hasil uji kembali akhir dan rasio Sharpe. Selain itu, perlu juga merujuk pada apakah ekspresi faktor itu sederhana, tidak peka terhadap ukuran pengelompokan, tidak peka terhadap interval penyesuaian posisi, tidak peka terhadap waktu awal pengujian ulang, dll.
Mengenai frekuensi penyesuaian posisi, pasar saham sering memiliki siklus 5 hari, 10 hari dan satu bulan, tetapi untuk pasar mata uang digital, siklus seperti itu tidak diragukan lagi terlalu lama, dan kondisi pasar di pasar riil dipantau dalam waktu riil, jadi sulit untuk berpegang pada siklus tertentu. Tidak perlu menyesuaikan posisi lagi, jadi dalam perdagangan riil, kami menyesuaikan posisi secara riil atau dalam jangka waktu pendek.
Mengenai cara menutup posisi, menurut metode tradisional, Anda dapat menutup posisi jika tidak ada dalam grup selama penyortiran berikutnya. Namun, dalam kasus penyesuaian posisi waktu nyata, beberapa mata uang mungkin berada di garis pemisah, dan posisi mungkin ditutup bolak-balik. Oleh karena itu, strategi ini mengadopsi pendekatan menunggu perubahan pengelompokan dan menutup posisi ketika perlu membuka posisi ke arah yang berlawanan. Misalnya, jika Anda melakukan long pada kelompok pertama, ketika mata uang pada posisi long dibagi menjadi kelompok ketiga, Anda dapat menutup posisi dan melakukan short. Jika Anda menutup posisi pada periode tertentu, seperti setiap hari atau setiap 8 jam, Anda juga dapat menutup posisi tanpa berada dalam grup. Anda dapat mencoba lebih lanjut.
#回测引擎
class Exchange:
def __init__(self, trade_symbols, fee=0.0004, initial_balance=10000):
self.initial_balance = initial_balance #初始的资产
self.fee = fee
self.trade_symbols = trade_symbols
self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance, 'fee':0, 'leverage':0, 'hold':0}}
for symbol in trade_symbols:
self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0}
def Trade(self, symbol, direction, price, amount):
cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
open_amount = amount - cover_amount
self.account['USDT']['realised_profit'] -= price*amount*self.fee #扣除手续费
self.account['USDT']['fee'] += price*amount*self.fee
self.account[symbol]['fee'] += price*amount*self.fee
if cover_amount > 0: #先平仓
self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #利润
self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
self.account[symbol]['amount'] -= -direction*cover_amount
self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
if open_amount > 0:
total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
total_amount = direction*self.account[symbol]['amount']+open_amount
self.account[symbol]['hold_price'] = total_cost/total_amount
self.account[symbol]['amount'] += direction*open_amount
def Buy(self, symbol, price, amount):
self.Trade(symbol, 1, price, amount)
def Sell(self, symbol, price, amount):
self.Trade(symbol, -1, price, amount)
def Update(self, close_price): #对资产进行更新
self.account['USDT']['unrealised_profit'] = 0
self.account['USDT']['hold'] = 0
for symbol in self.trade_symbols:
if not np.isnan(close_price[symbol]):
self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
self.account[symbol]['price'] = close_price[symbol]
self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*close_price[symbol]
self.account['USDT']['hold'] += self.account[symbol]['value']
self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)
self.account['USDT']['leverage'] = round(self.account['USDT']['hold']/self.account['USDT']['total'],3)
#测试因子的函数
def Test(factor, symbols, period=1, N=40, value=300):
e = Exchange(symbols, fee=0.0002, initial_balance=10000)
res_list = []
index_list = []
factor = factor.dropna(how='all')
for idx, row in factor.iterrows():
if idx.hour % period == 0:
buy_symbols = row.sort_values().dropna()[0:N].index
sell_symbols = row.sort_values().dropna()[-N:].index
prices = df_close.loc[idx,]
index_list.append(idx)
for symbol in symbols:
if symbol in buy_symbols and e.account[symbol]['amount'] <= 0:
e.Buy(symbol,prices[symbol],value/prices[symbol]-e.account[symbol]['amount'])
if symbol in sell_symbols and e.account[symbol]['amount'] >= 0:
e.Sell(symbol,prices[symbol], value/prices[symbol]+e.account[symbol]['amount'])
e.Update(prices)
res_list.append([e.account['USDT']['total'],e.account['USDT']['hold']])
return pd.DataFrame(data=res_list, columns=['total','hold'],index = index_list)
Faktor Volume: Melakukan aksi long pada koin dengan volume rendah dan melakukan aksi short pada koin dengan volume tinggi memberikan kinerja yang sangat baik, yang menunjukkan bahwa koin populer cenderung mengalami penurunan.
Faktor harga transaksi: beli mata uang berharga rendah, jual mata uang berharga tinggi, efeknya rata-rata.
Faktor jumlah transaksi: Kinerja sangat mirip dengan volume. Jelas bahwa korelasi antara faktor volume dan faktor jumlah transaksi sangat tinggi. Faktanya, korelasi rata-rata antara mata uang yang berbeda adalah 0,97, yang menunjukkan bahwa kedua faktor ini sangat mirip. Faktor ini perlu diperhitungkan. .
Faktor momentum 3h: (df_close - df_close.shift(3))/df_close.shift(3). Yaitu, kenaikan faktor selama 3 jam. Hasil backtest menunjukkan bahwa kenaikan selama 3 jam memiliki karakteristik regresi yang jelas, yaitu, kenaikan tersebut lebih cenderung turun pada periode berikutnya. Kinerja keseluruhannya bagus, tetapi ada juga periode kemunduran dan osilasi yang lebih panjang.
Faktor Momentum 24 jam: Hasil siklus penyeimbangan kembali 24 jam cukup bagus, dengan pengembalian yang serupa dengan momentum 3 jam dan penurunan yang lebih kecil.
Faktor perubahan turnover: df_volume.rolling(24).mean() / df_volume.rolling(96).mean(), yang merupakan rasio turnover hari terakhir terhadap turnover tiga hari terakhir. Posisi disesuaikan setiap 8 jam. Hasil uji ulang relatif baik dan retracement relatif rendah, yang menunjukkan bahwa saham dengan volume perdagangan aktif lebih mungkin jatuh.
Faktor perubahan nomor transaksi: df_count.rolling(24).mean() / df_count.rolling(96).mean(), yang merupakan rasio jumlah transaksi pada hari terakhir dengan jumlah transaksi dalam tiga hari terakhir Posisi disesuaikan setiap 8 jam. Hasil uji ulang relatif baik dan retracement relatif rendah, yang menunjukkan bahwa seiring bertambahnya jumlah transaksi, pasar cenderung jatuh lebih aktif.
Faktor perubahan nilai transaksi tunggal: -(df_volume.rolling(24).mean()/df_count.rolling(24).mean())/(df_volume.rolling(24).mean()/df_count.rolling(96).mean()) , yang merupakan rasio nilai transaksi hari terakhir terhadap nilai transaksi tiga hari terakhir, dan posisinya disesuaikan setiap 8 jam. Faktor ini juga sangat berkorelasi dengan faktor volume.
Faktor perubahan rasio transaksi aktif: df_buy_ratio.rolling(24).mean()/df_buy_ratio.rolling(96).mean(), yaitu rasio volume pembelian aktif terhadap total volume transaksi pada hari terakhir transaksi nilai dalam tiga hari terakhir, sesuaikan posisi setiap 8 jam. Faktor ini berkinerja baik dan memiliki sedikit korelasi dengan faktor volume.
Faktor volatilitas: (df_close/df_open).rolling(24).std(), yang memiliki efek tertentu saat mengambil posisi long pada mata uang dengan volatilitas rendah.
Faktor korelasi antara volume perdagangan dan harga penutupan: df_close.rolling(96).corr(df_volume), faktor korelasi antara harga penutupan dan volume perdagangan dalam 4 hari terakhir, kinerja keseluruhannya bagus.
Berikut ini adalah beberapa faktor berdasarkan kuantitas dan harga. Faktanya, kombinasi rumus faktor bisa sangat rumit dan mungkin tidak memiliki logika yang jelas. Anda dapat merujuk ke metode konstruksi faktor ALPHA101 yang terkenal: https://github.com/STHSF/alpha101.
#成交量
factor_volume = df_volume
factor_volume_res = Test(factor_volume, symbols, period=4)
factor_volume_res.total.plot(figsize=(15,6),grid=True);

#成交价
factor_close = df_close
factor_close_res = Test(factor_close, symbols, period=8)
factor_close_res.total.plot(figsize=(15,6),grid=True);

#成交笔数
factor_count = df_count
factor_count_res = Test(factor_count, symbols, period=8)
factor_count_res.total.plot(figsize=(15,6),grid=True);

print(df_count.corrwith(df_volume).mean())
0.9671246744996017
#3小时动量因子
factor_1 = (df_close - df_close.shift(3))/df_close.shift(3)
factor_1_res = Test(factor_1,symbols,period=1)
factor_1_res.total.plot(figsize=(15,6),grid=True);

#24小时动量因子
factor_2 = (df_close - df_close.shift(24))/df_close.shift(24)
factor_2_res = Test(factor_2,symbols,period=24)
tamenxuanfactor_2_res.total.plot(figsize=(15,6),grid=True);

#成交量因子
factor_3 = df_volume.rolling(24).mean()/df_volume.rolling(96).mean()
factor_3_res = Test(factor_3, symbols, period=8)
factor_3_res.total.plot(figsize=(15,6),grid=True);

#成交笔数因子
factor_4 = df_count.rolling(24).mean()/df_count.rolling(96).mean()
factor_4_res = Test(factor_4, symbols, period=8)
factor_4_res.total.plot(figsize=(15,6),grid=True);

#因子相关性
print(factor_4.corrwith(factor_3).mean())
0.9707239580854841
#单笔成交价值因子
factor_5 = -(df_volume.rolling(24).mean()/df_count.rolling(24).mean())/(df_volume.rolling(24).mean()/df_count.rolling(96).mean())
factor_5_res = Test(factor_5, symbols, period=8)
factor_5_res.total.plot(figsize=(15,6),grid=True);

print(factor_4.corrwith(factor_5).mean())
0.861206620552479
#主动成交比例因子
factor_6 = df_buy_ratio.rolling(24).mean()/df_buy_ratio.rolling(96).mean()
factor_6_res = Test(factor_6, symbols, period=4)
factor_6_res.total.plot(figsize=(15,6),grid=True);

print(factor_3.corrwith(factor_6).mean())
0.1534572192503726
#波动率因子
factor_7 = (df_close/df_open).rolling(24).std()
factor_7_res = Test(factor_7, symbols, period=2)
factor_7_res.total.plot(figsize=(15,6),grid=True);

#成交量和收盘价相关性因子
factor_8 = df_close.rolling(96).corr(df_volume)
factor_8_res = Test(factor_8, symbols, period=4)
factor_8_res.total.plot(figsize=(15,6),grid=True);

Penemuan faktor-faktor efektif yang terus-menerus tentu merupakan bagian terpenting dalam proses pembangunan strategi, namun tanpa metode sintesis faktor yang baik, maka satu faktor Alpha yang unggul tidak akan dapat memainkan perannya secara maksimal. Metode sintesis multi-faktor yang umum meliputi:
Metode bobot yang sama: Semua faktor yang akan disintesis ditambahkan dengan bobot yang sama untuk memperoleh faktor hasil sintesis baru.
Metode tertimbang dari pengembalian faktor historis: Semua faktor yang akan disintesis ditambahkan bersama-sama sesuai dengan rata-rata aritmatika pengembalian faktor historis dalam periode terkini sebagai bobot untuk memperoleh faktor-faktor tersintesis baru. Metode ini memberikan bobot lebih tinggi pada faktor yang berkinerja baik.
Memaksimalkan metode pembobotan IC_IR: Nilai IC rata-rata faktor komposit selama periode historis digunakan sebagai estimasi nilai IC faktor komposit pada periode berikutnya, dan matriks kovariansi nilai IC historis digunakan sebagai estimasi. volatilitas faktor komposit pada periode berikutnya. Berdasarkan IC_IR, sama dengan nilai yang diharapkan dari IC dibagi dengan deviasi standar IC, dan solusi bobot optimal untuk memaksimalkan faktor komposit IC_IR dapat diperoleh.
Metode analisis komponen utama (PCA): PCA adalah metode yang umum digunakan untuk reduksi dimensionalitas data. Korelasi antara faktor-faktor mungkin relatif tinggi, dan komponen-komponen utama setelah reduksi dimensionalitas digunakan sebagai faktor-faktor yang disintesis.
Artikel ini akan merujuk secara manual pada pembobotan validitas faktor. Metode yang dijelaskan di atas dapat merujuk ke:ae933a8c-5a94-4d92-8f33-d92b70c36119.pdf
Saat menguji satu faktor, urutannya tetap, tetapi sintesis multifaktor memerlukan penggabungan data yang sepenuhnya berbeda, sehingga semua faktor perlu distandarisasi, dan umumnya nilai ekstrem dan nilai yang hilang perlu dihilangkan. Di sini kami menggunakan df_volume\factor_1\factor_7\factor_6\factor_8 untuk sintesis.
#标准化函数,去除缺失值和极值,并且进行标准化处理
def norm_factor(factor):
factor = factor.dropna(how='all')
factor_clip = factor.apply(lambda x:x.clip(x.quantile(0.2), x.quantile(0.8)),axis=1)
factor_norm = factor_clip.add(-factor_clip.mean(axis=1),axis ='index').div(factor_clip.std(axis=1),axis ='index')
return factor_norm
df_volume_norm = norm_factor(df_volume)
factor_1_norm = norm_factor(factor_1)
factor_6_norm = norm_factor(factor_6)
factor_7_norm = norm_factor(factor_7)
factor_8_norm = norm_factor(factor_8)
factor_total = 0.6*df_volume_norm + 0.4*factor_1_norm + 0.2*factor_6_norm + 0.3*factor_7_norm + 0.4*factor_8_norm
factor_total_res = Test(factor_total, symbols, period=8)
factor_total_res.total.plot(figsize=(15,6),grid=True);

Artikel ini memperkenalkan metode pengujian faktor tunggal dan menguji faktor tunggal yang umum, dan secara awal memperkenalkan metode sintesis multifaktor. Namun, konten penelitian multifaktor sangat kaya, dan setiap poin yang disebutkan dalam artikel dapat diperluas secara mendalam. Ini adalah pendekatan yang layak untuk mengubah penelitian strategi tersebut menjadi penemuan faktor alfa. Menggunakan metodologi faktor dapat mempercepat verifikasi ide perdagangan, dan ada banyak materi referensi yang tersedia.
Alamat asli: https://www.fmz.com/robot/486605