pandas
Analiza: połączenie wszystkiego i podejmowanie decyzji
Szukaj…
Analiza kwintylowa: z losowymi danymi
Analiza kwintylowa stanowi powszechne ramy oceny skuteczności czynników bezpieczeństwa.
Co jest czynnikiem
Czynnikiem jest metoda oceniania / klasyfikowania zestawów papierów wartościowych. Dla określonego momentu w czasie i dla określonego zestawu papierów wartościowych czynnik może być reprezentowany jako seria pand, gdzie indeks jest tablicą identyfikatorów zabezpieczeń, a wartościami są wyniki lub stopnie.
Jeśli weźmiemy wyniki czynnikowe w czasie, możemy w każdym momencie podzielić zestaw papierów wartościowych na 5 równych koszyków lub kwintyli, w oparciu o kolejność wyników czynnikowych. Nie ma nic szczególnie świętego w liczbie 5. Mogliśmy użyć 3 lub 10. Ale często używamy 5. Na koniec śledzimy wydajność każdego z pięciu segmentów, aby ustalić, czy istnieje znacząca różnica w zwrotach. Zwykle skupiamy się bardziej na różnicy w zyskach segmentu o najwyższej randze w stosunku do najniższej.
Zacznijmy od ustawienia niektórych parametrów i generowania losowych danych.
Aby ułatwić eksperymentowanie z mechaniką, udostępniamy prosty kod do tworzenia losowych danych, aby dać nam wyobrażenie o tym, jak to działa.
Dane losowe obejmują
- Zwroty : generuj losowe zwroty dla określonej liczby papierów wartościowych i okresów.
- Sygnały : generuj losowe sygnały dla określonej liczby papierów wartościowych i okresów oraz z określonym poziomem korelacji ze zwrotami . Aby czynnik był użyteczny, musi istnieć pewna informacja lub korelacja między wynikami / stopniami a późniejszymi zwrotami. Gdyby nie było korelacji, zobaczylibyśmy ją. To byłoby dobre ćwiczenie dla czytelnika, powiel tę analizę losowymi danymi wygenerowanymi z korelacją
0
.
Inicjalizacja
import pandas as pd
import numpy as np
num_securities = 1000
num_periods = 1000
period_frequency = 'W'
start_date = '2000-12-31'
np.random.seed([3,1415])
means = [0, 0]
covariance = [[ 1., 5e-3],
[5e-3, 1.]]
# generates to sets of data m[0] and m[1] with ~0.005 correlation
m = np.random.multivariate_normal(means, covariance,
(num_periods, num_securities)).T
Teraz wygenerujmy indeks szeregów czasowych i indeks reprezentujący identyfikatory bezpieczeństwa. Następnie użyj ich do utworzenia ramek danych dla zwrotów i sygnałów
ids = pd.Index(['s{:05d}'.format(s) for s in range(num_securities)], 'ID')
tidx = pd.date_range(start=start_date, periods=num_periods, freq=period_frequency)
Dzielę m[0]
przez 25
aby zmniejszyć do czegoś, co wygląda jak zwrot z magazynu. Dodaję także 1e-7
aby uzyskać skromny pozytywny średni zwrot.
security_returns = pd.DataFrame(m[0] / 25 + 1e-7, tidx, ids)
security_signals = pd.DataFrame(m[1], tidx, ids)
pd.qcut
- Twórz pd.qcut
Użyjmy pd.qcut
aby podzielić moje sygnały na pd.qcut
dla każdego okresu.
def qcut(s, q=5):
labels = ['q{}'.format(i) for i in range(1, 6)]
return pd.qcut(s, q, labels=labels)
cut = security_signals.stack().groupby(level=0).apply(qcut)
Użyj tych cięć jako indeksu naszych zysków
returns_cut = security_returns.stack().rename('returns') \
.to_frame().set_index(cut, append=True) \
.swaplevel(2, 1).sort_index().squeeze() \
.groupby(level=[0, 1]).mean().unstack()
Analiza
Działka powraca
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(15, 5))
ax1 = plt.subplot2grid((1,3), (0,0))
ax2 = plt.subplot2grid((1,3), (0,1))
ax3 = plt.subplot2grid((1,3), (0,2))
# Cumulative Returns
returns_cut.add(1).cumprod() \
.plot(colormap='jet', ax=ax1, title="Cumulative Returns")
leg1 = ax1.legend(loc='upper left', ncol=2, prop={'size': 10}, fancybox=True)
leg1.get_frame().set_alpha(.8)
# Rolling 50 Week Return
returns_cut.add(1).rolling(50).apply(lambda x: x.prod()) \
.plot(colormap='jet', ax=ax2, title="Rolling 50 Week Return")
leg2 = ax2.legend(loc='upper left', ncol=2, prop={'size': 10}, fancybox=True)
leg2.get_frame().set_alpha(.8)
# Return Distribution
returns_cut.plot.box(vert=False, ax=ax3, title="Return Distribution")
fig.autofmt_xdate()
plt.show()
Wizualizuj korelację scatter_matrix
pomocą scatter_matrix
from pandas.tools.plotting import scatter_matrix
scatter_matrix(returns_cut, alpha=0.5, figsize=(8, 8), diagonal='hist')
plt.show()
Oblicz i wizualizuj maksymalny spadek
def max_dd(returns):
"""returns is a series"""
r = returns.add(1).cumprod()
dd = r.div(r.cummax()).sub(1)
mdd = dd.min()
end = dd.argmin()
start = r.loc[:end].argmax()
return mdd, start, end
def max_dd_df(returns):
"""returns is a dataframe"""
series = lambda x: pd.Series(x, ['Draw Down', 'Start', 'End'])
return returns.apply(max_dd).apply(series)
Jak to wygląda?
max_dd_df(returns_cut)
Wymyślmy to
draw_downs = max_dd_df(returns_cut)
fig, axes = plt.subplots(5, 1, figsize=(10, 8))
for i, ax in enumerate(axes[::-1]):
returns_cut.iloc[:, i].add(1).cumprod().plot(ax=ax)
sd, ed = draw_downs[['Start', 'End']].iloc[i]
ax.axvspan(sd, ed, alpha=0.1, color='r')
ax.set_ylabel(returns_cut.columns[i])
fig.suptitle('Maximum Draw Down', fontsize=18)
fig.tight_layout()
plt.subplots_adjust(top=.95)
Oblicz statystyki
Istnieje wiele potencjalnych statystyk, które możemy uwzględnić. Poniżej znajduje się tylko kilka, ale pokaż, jak łatwo możemy włączyć nowe statystyki do naszego podsumowania.
def frequency_of_time_series(df):
start, end = df.index.min(), df.index.max()
delta = end - start
return round((len(df) - 1.) * 365.25 / delta.days, 2)
def annualized_return(df):
freq = frequency_of_time_series(df)
return df.add(1).prod() ** (1 / freq) - 1
def annualized_volatility(df):
freq = frequency_of_time_series(df)
return df.std().mul(freq ** .5)
def sharpe_ratio(df):
return annualized_return(df) / annualized_volatility(df)
def describe(df):
r = annualized_return(df).rename('Return')
v = annualized_volatility(df).rename('Volatility')
s = sharpe_ratio(df).rename('Sharpe')
skew = df.skew().rename('Skew')
kurt = df.kurt().rename('Kurtosis')
desc = df.describe().T
return pd.concat([r, v, s, skew, kurt, desc], axis=1).T.drop('count')
Skończy się na tym, że użyjemy tylko funkcji describe
ponieważ łączy ona wszystkie pozostałe.
describe(returns_cut)
Nie ma to być wyczerpujące. Ma on na celu zebranie wielu funkcji pand i pokazanie, w jaki sposób możesz z nich skorzystać, aby pomóc odpowiedzieć na ważne pytania. Jest to podzbiór rodzajów wskaźników, których używam do oceny skuteczności czynników ilościowych.