Opublikowano:

Aktualizacja:

4. Algorytm Python dla rachunku XTB.

Sprawdzimy, jak działa prosty robot giełdowy, bazujący na strategii średnich kroczących. Wdrożono tu strategię średnich kroczących tylko i wyłącznie dla przykładu (w tym teście nie jest to istotne, czy strategia jest dochodowa).

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

© 2025 All Rights Reserved.

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