디지털 화폐 인수 모델

저자:초목, 창작: 2022-09-27 16:10:28, 업데이트: 2023-09-15 20:58:26

[TOC]

img

인자 모델 프레임워크

주식 시장의 다인자 모델에 대한 연구 보고서는 땀으로 가득 차 있으며, 풍부한 이론과 실습이 있다. 디지털 통화 시장은 동전 종의 수, 총 시장 가치, 거래 금액, 파생물 시장 등에 관계없이 요인 연구를 수행하기에 충분합니다. 이 문서는 주로 정량화 전략 초보자를 대상으로하며 복잡한 수학적 원리와 통계 분석을 포함하지 않으며, 통화 안정성 선물 시장을 데이터 소스로 사용하여 간단한 요인 연구 프레임워크를 구축하여 요인 지표를 평가 할 수 있습니다.

요인은 지표로 볼 수 있고, 표현으로 쓸 수 있으며, 요인은 끊임없이 변화하며, 미래의 수익 정보를 반영하며, 일반적으로 요인은 투자 논리를 나타냅니다.

예를 들어, 종결 가격 클로즈 요인은 주가가 미래의 수익을 예측할 수 있다는 가정에 근거하고, 주가가 높을수록 미래 수익이 높을 수도 있고 (또는 낮을 수도 있습니다) 이 요인을 기반으로 포트폴리오를 구성하는 것은 정기적으로 순차적으로 높은 가격 주식을 구매하는 투자 모델/전략입니다. 일반적으로는 지속적인 초과 수익을 창출할 수 있는 요인은 알파로 불립니다. 예를 들어 시장 가치 요인, 동력 요인 등은 학계와 투자계에서 효과가 있는 것으로 입증된 요인입니다.

주식 시장이나 디지털 통화 시장은 모두 복잡한 시스템이며, 미래 수익을 완전히 예측할 수있는 요인이 없지만 여전히 어느 정도의 예측 가능성을 가지고 있습니다. 효과적인 알파 (투자 모델) 는 더 많은 자금이 투입됨에 따라 점차 실패합니다. 그러나이 과정은 시장에서 다른 패턴을 생성하여 새로운 알파를 낳을 것입니다. 시장 가치 요인은 A 주식 시장에서 매우 효과적인 전략이었습니다. 단순히 가장 낮은 시장 가치의 10 개의 주식을 구입하고 매일 한 번 조정하여 2007 년부터 10 년 동안 400 배 이상의 수익을 얻을 수 있습니다. 그러나 2017 년 백마 주식 시장의 큰 가치는 소규모 시장 요인의 실패를 반영하고 가치 요인이 instead가 인기를 얻었습니다. 따라서 지속적인 실험과 알파의 사용과 시도와 균형을 맞추는 것이 필요합니다.

검색된 요인은 전략을 세우는 기초이며, 여러 가지 연관되지 않은 효과적인 요인을 조합하여 비교적 좋은 전략을 세울 수 있다.

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

데이터 소스

코인안USDT 상생 선물 2022년 초부터 현재까지의 시간 K선 데이터, 현재까지 150개 이상의 동전을 보유하고 있다. 앞서 언급했듯이, 인자 모델은 모든 동전보다는 특정 동전만을 대상으로 한 옵션 동전 모델이다. K선 데이터에는 초과 하락 가격, 거래량, 거래 수, 적극적인 구매량 등의 데이터가 포함되어 있으며, 이러한 데이터는 물론 미국 주식 지수, 인더스 예상, 수익성 체인 데이터, 소셜 미디어 열기 등 모든 요소의 소스가 아닙니다. 냉문 데이터 소스가 효과적인 알파를 발굴 할 수도 있지만 기본 가격 데이터는 충분히 충분합니다.

## 当前交易对
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)

아웃:

['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))

아웃:

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)

아웃:

Index(['time', 'open', 'high', 'low', 'close', 'amount', 'end_time', 'volume',
       'count', 'buy_amount', 'buy_volume', 'null'],
      dtype='object')

초기 K 라인 데이터에서 우리가 관심있는 데이터를 추출합니다: 종료 가격, 개시 가격, 거래량, 거래 지수, 적극적인 구매 비율, 이러한 데이터에 기반하여 필요한 요인을 처리합니다.

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')

이 지표의 전체적인 성과에 따르면 시장 지표는 비교적 비참한 것으로 나타났습니다.

df_norm = df_close/df_close.fillna(method='bfill').iloc[0] #归一化
df_norm.mean(axis=1).plot(figsize=(15,6),grid=True);
#最终指数收益图

img

요인효율 결정

  • 회귀법 다음 단계의 수익률은因변수로서, 시험중인因因자로서, 회귀되는 계수는因子의 수익률이다. 회귀 방정식을 구성한 후, 일반적으로 계수 t값의 절대값 평균값, 계수 t값의 절대값 순서 중 2보다 큰 비율, 연산因子의 수익률, 연산因子의 수익률 변동률, 연산因子의 수익률의 샤프 등의 매개 변수를 참조하여 계수의 효과와 변동성을 참조한다. 한 번에 여러 계수를 회귀할 수 있다.

  • IC, IR 등의 지표 요인 순위와 다음 기간 주식 수익률의 상관 계수인 IC라고 불리는 것은, 이제 일반적으로 RANK_IC로도 사용되고 있다. IR는 일반적으로 IC 계열의 평균값/IC 계열의 표준차차이다.

  • 계층 회귀법 이 문서는 이 방법을 사용하여, 테스트하고자 하는 요인 순서에 따라 동전을 N 그룹으로 분류하여 그룹 재검토를 수행하고, 고정된 주기를 사용하여 오퍼레이션을 수행합니다. 이상적인 경우, N 그룹 동전의 수익률은 단일화, 단일화 증가 또는 감소, 각 그룹의 수익 격차가 더 큰 것을 보여줍니다. 이러한 요인은 좋은 구별으로 나타납니다. 첫 번째 그룹이 가장 높은 수익률을 보이고 마지막 그룹이 가장 낮은 수익률을 보이고 있다면, 첫 번째 조합을 만들고 마지막 조합을 더 빈 채로 만들어서 최종 수익률, 샤프 비율의 기준 지표를 얻습니다.

실제 재검토 작업

요인별로 소부터 큰까지의 순서에 따라 유예 동전을 3개 그룹으로 분류하고, 각 그룹은 약 1/3을 차지하며, 하나의 요소가 유효하다면 각 구성 요소의 수가 적으면 종종 수익률이 높지만, 또한 각 동전으로 할당되는 자금이 상대적으로 더 많다는 것을 의미합니다. 많은 빈 공간이 각각 두 배의 리버웨이, 첫 번째 그룹과 마지막 그룹이 각각 10개의 동전이라면 비중 비율이 10%이며, 빈 공간에 있는 특정 동전이 2배로 상승하면 20%가 퇴출됩니다. 해당 분포가 50이면 퇴출됩니다. 4%의 분포 동전은 블랙 스탠의 위험을 줄일 수 있습니다. 첫 번째 다중을 만들 수 있습니다. (인자 최소), 빈 세 번째 그룹. 더 큰 인자가 더 높으면 수익률이 높습니다.

일반적으로 최종 재검토의 수익률과 샤프 비율에 따라 요인 예측 능력을 대략적으로 평가할 수 있다. 또한 요인 표현식이 단순하거나, 분포 크기에 민감하지 않거나, 조정 간격에 민감하지 않거나, 재검토의 초기 시간에 민감하지 않은지 등을 참조해야 한다.

거래의 빈도에 관해서는 주식 시장은 종종 5일, 10일 및 1개월의 주기로 진행되지만, 디지털 통화 시장의 경우 이러한 주기는 의심할 여지없이 너무 길고 실제 시장의 시장은 실시간으로 모니터링되며 특정 주기에 따라 재조정이 필요하지 않으므로 실제 시장에서 우리는 실시간 또는 단시간 주기를 조정합니다.

평형화 방법에 대해서는, 전통적인 방법으로, 다음 정렬시 그룹에 있지 않은 상태에서 평형화될 수 있다. 그러나 실시간 정렬시 상황에서, 일부 동전은 분계점에 있을 수 있으며, 역평형의 상황이 발생할 수 있다. 따라서 이 전략은 그룹 변경을 기다린 채, 역방향 포지션이 필요할 때 다시 평형화, 예를 들어 첫 번째 그룹에서 더 많은 것을 할 때, 많은 상태의 동전이 세 번째 그룹으로 나뉘어지면 다시 평형화 빈 상태에서 다시 평형화 할 수 있다. 고정 평형화 주기가 있다면, 예를 들어 매일 또는 8 시간마다 평형화 방법이 사용될 수 있다.

#回测引擎
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)

간단한 요인 테스트

거래량 요인: 단순하게 거래량이 적은 통화, 거래량이 높은 통화, 매우 좋은 성과를 나타냅니다. 이것은 인기있는 코인이 더 떨어지는 경향이 있음을 보여줍니다.

거래 가격 요인: 더 많은 가격으로 낮은 화폐를 만들고, 높은 가격으로 높은 화폐를 만들고, 효과는 일반적입니다.

거래소수 요인: 성과와 거래량이 매우 유사하다. 거래소수 요인과 거래소수 요인의 상관관계가 매우 높다는 것을 분명히 볼 수 있으며 실제로도 마찬가지이며, 각 다른 통화의 평균 상관관계가 0.97에 달하는 것으로 나타났습니다. 두 요인이 매우 가깝다는 것을 보여줍니다. 복수 요인을 합성할 때이 요인을 고려해야합니다.

3h 운동량 인자: ((df_close - df_close.shift)) 3)) /df_close.shift ((3)); 즉 인자의 3시간 상승, 리코테스트 결과 3시간 상승은 상승한 것이 더 쉽게 떨어지는 것을 나타내는 명백한 회귀 특성을 가지고 있음을 볼 수 있습니다. 전체적인 성능은 좋습니다. 그러나 더 긴 회퇴와 오스컬레이션 기간도 있습니다.

24h 운동량 인수는 24h의 교정 주기가 좋은 결과로, 3h의 운동량과 가까운 수익, 더 작은 회귀를 얻습니다.

거래량 변화 요인:df_volume.rolling ((24).mean))) /df_volume.rolling ((96).mean ((), 즉 최근 1일 거래량과 최근 3일 거래량의 비율, 8시간마다 한 번 조정한다. 재검사 결과는 비교적 좋고, 역퇴도 상대적으로 낮다. 이는 거래량이 활발하고 오히려 하락하는 경향이 있음을 나타낸다.

거래량 변화 요인:df_count.rolling ((24).mean (() /df_count.rolling ((96).mean ((), 즉 최근 1일 거래량과 최근 3일 거래량의 비율, 8시간에 한 번 조정한다. 재검사 결과는 비교적 좋고, 회귀도 상대적으로 낮다. 이는 거래량 증가가 활발한 것이 아니라 감소하는 경향이 있음을 나타낸다.

단편 거래의 가치 변동 요인: - ((df_volume.rolling(24).mean()/df_count.rolling(24.mean())/(df_volume.rolling(24.mean()/df_count.rolling ((96).mean()) 즉, 최근 1일 거래 가치와 최근 3일 거래 가치의 비율로, 8시간마다 한 번 거래를 조정한다. 이 요인은 또한 거래량 요인과 매우 관련이 있다.

적극적인 거래 비율 변화 요인:df_buy_ratio.rolling ((24).mean (() /df_buy_ratio.rolling ((96).mean ((), 즉 최근 1일 동안의 적극적인 구매량과 전체 거래량의 비율과 최근 3일 동안의 거래 가치의 비율, 8시간마다 한 번 조정한다. 이 요인은 아직 나타나지 않고 있으며 거래량 요인과 관련이 거의 없다.

변동률 요인: (df_close/df_open).rolling ((24)).std ((), 많은 변동성을 가진 작은 화폐를 만드는 데 효과가 있다.

거래량과 폐쇄 가격의 상관 요소:df_close.rolling ((96).corr ((df_volume), 최근 4 일간의 종료 가격과 거래량 관련 요소, 전반적으로 좋은 성과.

이 목록은 양값에 기초한 몇 가지 요인일 뿐이지만, 실제로 요인 공식 조합은 매우 복잡할 수 있으며, 명백한 논리가 없을 수 있다. 유명한 ALPHA101의 요인 구조를 참조할 수 있다: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);

img

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

img

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

img

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);

img

#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);

img

#成交量因子
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);

img

#成交笔数因子
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);

img

#因子相关性
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);

img

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);

img

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);

img

#成交量和收盘价相关性因子
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);

img

다중 인자 합성

새로운 유효 인자를 지속적으로 발굴하는 것은 전략 구축 과정의 가장 중요한 부분이지만, 좋은 인자 합성 방법이 없으면 훌륭한 단일 알파 인자가 가장 큰 역할을 할 수 없습니다. 일반적인 다인자 합성 방법은 다음과 같습니다.

평행률법: 합성 요인 등 모든 가중을 더하여 새로운 합성 후 요인을 얻는다.

역사 요인수익률 가중화법칙: 모든 합성 요인을 최근 기간 동안의 역사 요인수익률의 수학적 평균에 따라 가중화하여 더하여 새로운 합성 후 요인을 얻는다. 이 방법이 잘 나타낸 요인중량은 더 높다.

최대화 IC_IR 곱셈법: 역사 기간 동안의 복합 인자 평균 IC 값은 복합 인자의 다음 시기의 IC 값의 추정치로, 역사 IC 값의 동사분차 매트리지는 복합 인자의 다음 시기의 변동율의 추정치로, IC_IR가 IC의 기대값과 IC의 표준편차로 나눈 값에 해당하는 경우 최대화 복합 인자 IC_IR의 최우선 재해결을 얻을 수 있다.

주성분석 (PCA) 방법: PCA는 데이터 축소의 일반적인 방법이며, 요인 간의 상관관계가 상대적으로 높을 수 있으며, 축소 후 주성분자를 합성 후 요인으로 사용합니다.

이 문서는 수동으로 요인효율 권한을 참조한다. 위의 방법들은 참조될 수 있다:ae933a8c-5a94-4d92-8f33-d92b70c36119.pdf

단일 인자를 테스트할 때 정렬은 고정되어 있지만 다인자 합성은 완전히 다른 데이터를 결합해야 하며, 따라서 모든 인자를 표준화 처리해야 하며, 일반적으로 극값과 누락값 처리도 필요합니다. 여기서는df_volume\factor_1\factor_7\factor_6\factor_8 합성을 사용합니다.

#标准化函数,去除缺失值和极值,并且进行标准化处理
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);

img

요약

이 문서는 단일 인자 테스트 방법을 소개하고 일반적인 단일 인자를 테스트하고, 다중 인자 합성 방법을 처음 소개하지만, 다중 인자 연구는 매우 풍부합니다. 문서는 각 점에 대해 깊숙이 전개 할 수 있다고 언급하고, 다양한 전략 연구를 알파 인자 발굴으로 전환하는 것은 실행 가능한 방법입니다. 인자 방법을 사용하여 거래 아이디어를 검증하는 데 큰 속도를 낼 수 있으며 많은 자료가 있습니다.

실제 주소:https://www.fmz.com/robot/486605


관련

더 많은

정말 좋은 글입니다.

버린을 떠났어요草神威武!!! 최근에도 연구중입니다.

가벼운 구름끝났습니다. 완전히 이해가 안되네요.

cjz140이!

jmxjqr0302이!

jmxjqr0302이!

jmxjqr0302이!

f_q이!

무수히 많은 오징어이!

튜투001이!

펑91이!