Opublikowano:
Aktualizacja:
W tej części wykonana zostanie w Pythonie uproszczona analiza skuteczności strategii przecinających się średnich kroczących. Założenia strategii są takie, że kupujemy, gdy średnia krocząca szybka przetnie średnią kroczącą wolną, natomiast sprzedajemy, gdy jest na odwrót.
Analiza jest uproszczona, ponieważ nie zakłada żadnych opóźnień w realizacji zleceń, prowizji brokera, spreadu ani swapu.
Rozpoczynamy tak jak w poprzedniej części od importu danych i obliczeniu średnich ze stu ostatnich świec (dodatkowo dodajemy bibliotekę matplotlib):
import pandas as pd
import plotly.graph_objects as go
import matplotlib.pyplot as plt
df=pd.read_csv('/content/drive/My Drive/dane_historyczne/dax.csv')
df2=df.drop(['Wolumen'], axis=1)
df2=df2[-100:]
l_usrednien_H=13
l_usrednien_L=3
df2['sr1'] =df2['Zamkniecie'].ewm(span=l_usrednien_H, adjust=False).mean()
df2['sr2'] =df2['Zamkniecie'].ewm(span=l_usrednien_L, adjust=False).mean()
df3=df2[l_usrednien_H:]
df3 = df3.reset_index(drop=True)
df3.tail()
Tworzymy pomocniczą kolumnę o nazwie ‘cross’ w strukturze danych df3. W kolumnie tej zapisana zostanie informacja, czy średnia krocząca szybka jest większa, czy mniejsza równa od średniej kroczącej wolnej.
df3['cross'] =df3['sr2']>df3['sr1']
df3.tail()
Sprawdzimy dla których indeksów, następuje sygnał na wzrost oraz dla których indeksów następuje sygnał na spadek:
byk=[]
niedzwiedz=[]
for indeks in range(len(df3)):
if indeks>0 and df3['cross'].iloc[indeks]==1 and df3['cross'].iloc[indeks-1]==0:
byk.insert(indeks,df3.index[indeks])
for indeks in range(len(df3)):
if indeks>0 and df3['cross'].iloc[indeks]==0 and df3['cross'].iloc[indeks-1]==1:
niedzwiedz.insert(indeks,df3.index[indeks])
print("Indeksy przecięcia się średnich na wzrost:", byk)
print("Indeksy przecięcia się średnich na spadek:",niedzwiedz)
Możemy narysować wykres z naniesionymi liniami sygnałów – niebieskie pionowe linie przerywane to sygnał na wzrost, natomiast linie zielone to sygnał na spadek.
fig = go.Figure(data=[go.Candlestick(x=df3.index,
open=df3['Otwarcie'],
high=df3['Najwyzszy'],
low=df3['Najnizszy'],
close=df3['Zamkniecie'])])
fig.add_trace(go.Scatter(x=df3.index, y=df3['sr1'],name='sr1'))
fig.add_trace(go.Scatter(x=df3.index, y=df3['sr2'],name='sr2'))
for indeks in range(len(byk)):
fig.add_shape(type="line",x0=byk[indeks], y0=0, x1=byk[indeks], y1=1,xref='x', yref='paper',line=dict(color="Blue",width=1,dash="dot"))
for indeks in range(len(niedzwiedz)):
fig.add_shape(type="line",x0=niedzwiedz[indeks], y0=0, x1=niedzwiedz[indeks], y1=1,xref='x', yref='paper',line=dict(color="Green",width=1,dash="dot"))
fig.update_layout(xaxis_rangeslider_visible=False)
fig.show()
Sprawdzimy dla jakich indeksów otwieramy pozycję dla gry na wzrost:
for indeks1 in byk:
print("Indeks otwarcia pozycji:",indeks1)
for indeks2 in niedzwiedz:
if indeks2>indeks1:
print("Indeks zamknięcia pozycji:",indeks2)
break
print()
Sprawdzimy dla jakich indeksów otwieramy pozycję dla gry na spadek:
for indeks2 in niedzwiedz:
print("Indeks otwarcia pozycji:",indeks2)
for indeks1 in byk:
if indeks1>indeks2:
print("Indeks zamknięcia pozycji:",indeks1)
break
print()
Można zauważyć, że ostatnia pozycja została otwarta i nie została zamknięta (średnie nie przecięły się). Otwarta pozycja nie zostanie uwzględniona w dalszych kalkulacjach.
Sprawdzamy ile punktów zarabiamy lub tracimy grając na wzrosty:
#zagrania na wzrost
bilans1=0
for indeks1 in byk:
print("Otwarcie:",df3['Zamkniecie'][indeks1])
for indeks2 in niedzwiedz:
if indeks2>indeks1:
print("Zamknięcie:",df3['Zamkniecie'][indeks2])
profit=df3['Zamkniecie'][indeks2]-df3['Zamkniecie'][indeks1]
print("Profit:","{:.1f}".format(profit),"punktów")
bilans1=bilans1+profit
break
print()
print("Bilans gry na wzrost:","{:.1f}".format(bilans1),"punktów")
Uwaga: poleceniem – “{:.1f}”.format() – formatuje się liczbę do jednego miejsca po przecinku.
Sprawdzamy ile punktów zarabiamy lub tracimy grając na spadki:
#zagrania na spadek
bilans2=0
for indeks2 in niedzwiedz:
print("Otwarcie:",df3['Zamkniecie'][indeks2])
for indeks1 in byk:
if indeks1>indeks2:
print("Zamknięcie:",df3['Zamkniecie'][indeks1])
profit=df3['Zamkniecie'][indeks1]-df3['Zamkniecie'][indeks2]
print("Profit:","{:.1f}".format(profit),"punktów")
bilans2=bilans2+profit
break
print()
print("Bilans gry na spadek:","{:.1f}".format(bilans2),"punktów")
Obliczamy całkowity bilans zysków/strat:
print("Bilans:","{:.1f}".format(bilans1+bilans2),"punktów")
Jeśli chcemy wykreślić wykres zależności bilansu od numeru świecy, można scalić dane dla gry na wzrost oraz na spadek:
Modyfikujemy poprzedni kod, aby utworzyć strukturę danych z informacją o indeksie i proficie każdej transakcji na wzrost:
#zagrania na wzrost
ind_byk=[]
prof_byk=[]
for indeks1 in byk:
for indeks2 in niedzwiedz:
if indeks2>indeks1:
profit=df3['Zamkniecie'][indeks2]-df3['Zamkniecie'][indeks1]
prof_byk.insert(0,profit)
ind_byk.insert(0,indeks2)
break
dx = pd.DataFrame()
dx['indeks'] =ind_byk
dx['profit'] =prof_byk
dx
Modyfikujemy również kod, aby utworzyć strukturę danych z informacją o indeksie i proficie każdej transakcji na spadek:
#zagrania na spadek
bilans2=0
ind_niedzwiedz=[]
prof_niedzwiedz=[]
for indeks2 in niedzwiedz:
for indeks1 in byk:
if indeks1>indeks2:
profit=df3['Zamkniecie'][indeks1]-df3['Zamkniecie'][indeks2]
prof_niedzwiedz.insert(0,profit)
ind_niedzwiedz.insert(0,indeks1)
break
dy = pd.DataFrame()
dy['indeks'] =ind_niedzwiedz
dy['profit'] =prof_niedzwiedz
dy
Scalamy w jedną strukturę danych, sortujemy oraz resetujemy indeks:
result = pd.concat([dx, dy])
dn=result.sort_values(by=['indeks'])
dn = dn.reset_index(drop=True)
dn
Obliczami i dodajemy nową kolumnę z bilansem:
bilans=[]
for indeks2 in range(len(dn)):
if indeks2>0:
bilans.insert(indeks2,dn['profit'][indeks2]+bilans[-1])
else:
bilans.insert(indeks2,dn['profit'][indeks2])
dn['bilans'] =bilans
display(dn)
print("Sprawdzenie:","{:.1f}".format(sum(dn['profit'])), "punktów")
Możemy narysować wykres:
x = dn['indeks']
y = dn['bilans']
plt.figure(figsize=(20, 5))
plt.plot(x, y)
plt.xlabel("Indeks świecy")
plt.ylabel("Zysk/Strata")
plt.show()
Możemy obliczyć jaka historycznie była największa strata oraz największy zysk.
print("Liczba zamkniętych pozycji:",len(dn))
print("Największa całkowita strata:","{:.1f}".format(dn['bilans'].min()), "punktów")
print("Największy całkowity zysk:","{:.1f}".format(dn['bilans'].max()), "punktów")
Całościowo, kod dla naszej analizy przedstawiono poniżej. Tym razem przetestowano strategię dla 1000 ostatnich świec.
import pandas as pd
import plotly.graph_objects as go
import matplotlib.pyplot as plt
df=pd.read_csv('/content/drive/My Drive/dane_historyczne/dax.csv')
df2=df.drop(['Wolumen'], axis=1)
df2=df2[-1000:]
l_usrednien_H=13
l_usrednien_L=3
df2['sr1'] =df2['Zamkniecie'].ewm(span=l_usrednien_H, adjust=False).mean()
df2['sr2'] =df2['Zamkniecie'].ewm(span=l_usrednien_L, adjust=False).mean()
df3=df2[l_usrednien_H:]
df3 = df3.reset_index(drop=True)
df3['cross'] =df3['sr2']>df3['sr1']
byk=[]
niedzwiedz=[]
for indeks in range(len(df3)):
if indeks>0 and df3['cross'].iloc[indeks]==1 and df3['cross'].iloc[indeks-1]==0:
byk.insert(indeks,df3.index[indeks])
for indeks in range(len(df3)):
if indeks>0 and df3['cross'].iloc[indeks]==0 and df3['cross'].iloc[indeks-1]==1:
niedzwiedz.insert(indeks,df3.index[indeks])
#zagrania na wzrost
ind_byk=[]
prof_byk=[]
for indeks1 in byk:
for indeks2 in niedzwiedz:
if indeks2>indeks1:
profit=df3['Zamkniecie'][indeks2]-df3['Zamkniecie'][indeks1]
prof_byk.insert(0,profit)
ind_byk.insert(0,indeks2)
break
dx = pd.DataFrame()
dx['indeks'] =ind_byk
dx['profit'] =prof_byk
#zagrania na spadek
bilans2=0
ind_niedzwiedz=[]
prof_niedzwiedz=[]
for indeks2 in niedzwiedz:
for indeks1 in byk:
if indeks1>indeks2:
profit=df3['Zamkniecie'][indeks1]-df3['Zamkniecie'][indeks2]
prof_niedzwiedz.insert(0,profit)
ind_niedzwiedz.insert(0,indeks1)
break
dy = pd.DataFrame()
dy['indeks'] =ind_niedzwiedz
dy['profit'] =prof_niedzwiedz
result = pd.concat([dx, dy])
dn=result.sort_values(by=['indeks'])
dn = dn.reset_index(drop=True)
bilans=[]
for indeks2 in range(len(dn)):
if indeks2>0:
bilans.insert(indeks2,dn['profit'][indeks2]+bilans[-1])
else:
bilans.insert(indeks2,dn['profit'][indeks2])
dn['bilans'] =bilans
x = dn['indeks']
y = dn['bilans']
plt.figure(figsize=(20, 5))
plt.plot(x, y)
plt.xlabel("Indeks świecy")
plt.ylabel("Zysk/Strata")
plt.show()
print("Całkowity bilans:","{:.1f}".format(sum(dn['profit'])), "punktów")
print("Liczba zamkniętych pozycji:",len(dn))
print("Największa całkowita strata:","{:.1f}".format(dn['bilans'].min()), "punktów")
print("Największy całkowity zysk:","{:.1f}".format(dn['bilans'].max()), "punktów")
Zastosowanie strategii przecinających się średnich kroczących w zaprezentowanym powyżej przykładzie przynosi zmienne rezultaty w różnych okresach czasu. Są okresy w których strategia może być dochodowa, są okresy, gdy właściciel rachunku inwestycyjnego może tracić.
© 2024 All Rights Reserved.
Cookie | Duration | Description |
---|---|---|
cookielawinfo-checkbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checkbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |
Kopiowanie wszystkich kodów tylko dla użytkowników PREMIUM.