Blog - inwestuj.biz

Opublikowano:

Aktualizacja:

5. Prosta optymalizacja algorytmu.

W poprzednim artykule zaprezentowano test strategii polegającej na algotradingu generowanego sygnałami przecinających się dwóch wartości średnich kroczących – wolnej oraz szybkiej. Dla przypomnienia poniżej przedstawiono kod źródłowy do analizy 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")
				
			

Podstawowe parametry powyższej analizy to: średnia wolna – 13 świeczek oraz średnia szybka- 3 świeczki. 

Bilans zastosowania algorytmu był dodatni i wynosił 12223 punkty. Pojawia się jednak pytanie – czy liczby uśredniania 13 i 3 są optymalne? A może należy zastosować np. liczby 10 i 5? Oczywiście można ręcznie wypisywać w powyższy kod różne średnie i notować wyniki w arkuszu kalkulacyjnym. Dla większej ilości parametrów będzie to bardzo czasochłonne. 

Najprościej można dodać dwie pętle for i sprawdzić wszystkie rozwiązania z zdefiniowanego zakresu parametrów.  

Poniżej znajduje się kod programu do przykładowego sprawdzenia, jakie parametry uśredniania są najlepsze:

				
					l_usrednien_H_start=3
l_usrednien_H_stop=15
l_usrednien_H_krok=1

l_usrednien_L_start=2
l_usrednien_L_stop=14
l_usrednien_L_krok=1

optimum_df = pd.DataFrame(columns=range(l_usrednien_L_start,l_usrednien_L_stop+1,l_usrednien_L_krok))
for i in range(l_usrednien_L_start,l_usrednien_L_stop+1,l_usrednien_L_krok):
  l_usrednien_L=i
  lista=[]
  for j in range(l_usrednien_H_start,l_usrednien_H_stop+1,l_usrednien_H_krok):
    l_usrednien_H=j

    if l_usrednien_H>l_usrednien_L:
      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']
      
      lista.insert(len(lista),sum(dn['profit']))
    else:
      lista.insert(len(lista),nan)

  optimum_df[l_usrednien_L]=lista

optimum_df.index = pd.RangeIndex(l_usrednien_H_start,l_usrednien_H_stop+1,l_usrednien_H_krok)

def simple_median_style(s: pd.Series, true_css: str, false_css: str = '') -> np.ndarray:
    return np.where(s >= optimum_df.max().max(), true_css, false_css)

display(optimum_df.style.apply(simple_median_style, true_css='background-color: lightgreen'))
				
			

W rezultacie otrzymano tabelę wyników. Największe dodatni bilans transakcji osiągamy w dwóch przypadkach (zaznaczonych w tabeli na zielono):

1. Dla średniej wolnej równej 15 świec oraz średniej szybkiej 4 świece.

2. Dla średniej wolnej równej 15 świec oraz średniej szybkiej 5 świece.

W obu przypadkach algorytm uzyskałby bilans 1415 punktów. 

Symbolem “nan” oznaczono zakres parametrów dla których wartość średniej wolnej jest mniejsza lub równa wartości średniej szybkiej (co jest sprzeczne z założeniami strategii).

© 2024 All Rights Reserved.

Kopiowanie wszystkich kodów tylko dla użytkowników PREMIUM.