Podstawy języka Python do handlu algorytmicznego
Traderzy używają języka Python do budowania botów handlowych, wskaźników technicznych, wtyczek i innych narzędzi wspomagających handel algorytmiczny lub operacje manualne, a ten artykuł wyjaśnia podstawy kodowania w języku Python.
Python to popularny, wysokopoziomowy, ogólnego przeznaczenia język programowania używany do tworzenia stron internetowych, nauki o danych, automatyzacji, a ostatnio także do handlu algorytmicznego w cTrader. Niezależnie od tego, czy tworzysz proste boty handlowe oparte na sygnałach, czy złożone strategie wielowskaźnikowe, Python sprawia, że proces jest szybszy, bardziej wydajny i łatwiejszy w zarządzaniu.
Algorytmy w języku Python w jedną minutę!
- Korzystaj z wbudowanego wsparcia języka Python i bezproblemowego dostępu do cTrader Algo API, przy czym cTrader jest jedyną dużą platformą oferującą natywną integrację od razu po instalacji. Nie są wymagane żadne wtyczki, adaptery ani skomplikowane konfiguracje.
- Skup się bardziej na tym, co Twoja strategia powinna osiągnąć, ponieważ logika staje się łatwiejsza do złożenia. Ciesz się szybką iteracją, komponentami wielokrotnego użytku i skalowalną wydajnością.
- Rozwijaj szybko, debuguj mądrzej i współpracuj bez barier. Twój kod zawsze będzie adaptowalny, niezawodny i łatwy w utrzymaniu.
- Uzyskaj dostęp i korzystaj z tysięcy darmowych/open-source bibliotek, szczegółowych samouczków, przykładów kodu i silnego wsparcia społeczności na całym świecie.
Zmienne i typy danych
W języku Python zmienne są dynamicznie typowane, co oznacza, że nie musisz jawnie deklarować ich typów danych. Interpreter określa typ w czasie wykonywania na podstawie przypisanej wartości.
Zmienne tworzy się po prostu przypisując wartość do jednej z nich:
1 2 3 4 | |
Popularne typy danych
| Typ | Opis | Przykład |
|---|---|---|
int | Liczby całkowite | 5, 100, api.StepPips |
float | Liczby dziesiętne | 1.1234, 100.5, api.Symbol.Ask |
bool | Wartości logiczne | True, False |
str | Ciągi znaków | "EURUSD", api.Label |
list | Kolekcja elementów | [1, 2, 3], [p for p in api.Positions] |
W algorytmach cTrader zmienne przechowują ważne dane związane z informacjami rynkowymi, decyzjami handlowymi i konfiguracją cBota. Te zmienne często reprezentują obliczone wolumeny handlowe, wartości wskaźników, flagi logiczne, nazwy symboli, etykiety i więcej.
Oto przykład:
1 2 3 4 | |
W tym przypadku self.volumeInUnits to float używany do składania zleceń, podczas gdy self.enoughMoney to bool kontrolujący, czy kontynuować otwieranie pozycji w strategii gridowej.
Klasy i obiekty
Python to obiektowy język programowania (OOP), zapewniający narzędzia do organizowania kodu poprzez klasy i obiekty, które modelują rzeczywiste encje i zachowania. Klasa definiuje schemat tworzenia obiektów, które są wystąpieniami tej klasy z własnymi unikalnymi danymi i zachowaniami. Kluczowe koncepcje przedstawiono poniżej:
- Klasa jest definiowana za pomocą słowa kluczowego
class. - Metoda
__init__(konstruktor) jest powszechnie używana do inicjalizacji stanu obiektu. - Metody instancji definiują zachowanie.
- Atrybuty przechowują dane specyficzne dla każdego obiektu.
Na przykład możesz utworzyć klasę Car:
1 2 3 4 5 6 7 | |
Następnie możesz tworzyć obiekty klasy Car i wchodzić z nimi w interakcje:
1 2 3 | |
W kontekście cTrader
W cTrader cBoty, wskaźniki i wtyczki są implementowane jako klasy, które hermetyzują całą swoją logikę. Algorytmy wchodzą w interakcję z platformą cTrader za pomocą specjalnego obiektu api, który zapewnia dostęp do symboli, wykresów, zleceń, wskaźników i więcej.
Możesz utworzyć klasę SimplecBot w cTrader w ten sposób:
1 2 3 | |
Klasa SimplecBot zawiera pojedynczą metodę (on_start(self)), która wykonuje się raz, gdy bot handlowy się uruchamia. Funkcja api.Print zapisuje wiadomość do dziennika, demonstrując, jak metody obiektów hermetyzują zachowanie handlowe.
Każde wystąpienie klasy skutecznie reprezentuje samodzielny algorytm handlowy, który zarządza własnym cyklem życia i decyzjami handlowymi przy użyciu zasad OOP. W standardowym cBocie cTrader klasa może przechowywać wewnętrzne dane stanu, takie jak wolumen, wyniki wskaźników itp., i używać kilku metod do zarządzania logiką handlową.
Rozważ ten przykład MACD crossover, który inicjalizuje wskaźnik MACD po uruchomieniu i składa zlecenie kupna, gdy wystąpi sygnał MACD crossover:
1 2 3 4 5 6 7 | |
Słowo kluczowe self
Wewnątrz klasy self odnosi się do wystąpienia klasy i zapewnia dostęp do jej zmiennych i metod. self jest używane do:
- Przechowywania danych, takich jak wyniki wskaźników, wolumeny pozycji i wartości konfiguracyjne.
- Śledzenia stanu wewnętrznego w różnych wywołaniach metod, takich jak
on_start(),on_tick()lubon_bar_closed().
Ten przykład demonstruje, jak używane jest self:
1 2 3 4 | |
W tym przypadku self.volume przechowuje obliczony wolumen do użycia w transakcjach, podczas gdy self.macd przechowuje obiekt wskaźnika MACD, umożliwiając dostęp do jego wartości przez cały cykl życia cBota. Bez self te zmienne byłyby lokalne dla on_start() i niedostępne w on_bar_closed(), gdzie mogą być podejmowane decyzje handlowe.
Metody i funkcje
Funkcje to bloki kodu wielokrotnego użytku używane do wykonywania określonego zadania. Gdy funkcje są definiowane wewnątrz klasy, nazywane są metodami i działają na wewnętrznym stanie klasy za pomocą parametru self. W kontekście handlu algorytmicznego z cTrader metody definiują, jak Twój algorytm handlowy zachowuje się w różnych warunkach, takich jak tiki rynkowe, zamknięcia słupków lub inicjalizacja.
Platforma automatycznie wywołuje specjalne metody (znane jako procedury obsługi zdarzeń) w odpowiednich momentach, takie jak:
on_start(self) – wywoływana raz, gdy bot jest inicjalizowany.
1 2 | |
on_tick(self) – wywoływana przy każdym przychodzącym tiku rynkowym.
1 2 | |
on_bar_closed(self) – wywoływana, gdy zamyka się nowa świeca/słupek (idealna dla strategii opartych na czasie).
1 2 3 4 | |
Metody niestandardowe lub pomocnicze
Aby uniknąć przepisywania i duplikowania kodu, możesz definiować własne metody. Takie metody niestandardowe powinny hermetyzować wspólną logikę, którą Twój robot handlowy może ponownie wykorzystać.
Poniższa metoda zwraca wszystkie otwarte pozycje powiązane z etykietą bieżącego cBota, ułatwiając konsekwentne śledzenie lub zamykanie pozycji.
1 2 | |
Rozważ inną metodę, która oblicza odległość w pipsach między bieżącą ceną a ceną otwarcia pozycji, co jest kluczowe dla decyzji w strategiach opartych na gridzie.
1 2 | |
Po zdefiniowaniu metody możesz ją wywołać z poziomu tej samej klasy za pomocą słowa kluczowego self. To podejście pozwala ponownie wykorzystać logikę w dowolnym miejscu w Twoim bocie bez duplikowania kodu.
Na przykład, po zdefiniowaniu get_bot_positions(), możesz wywołać tę funkcję wewnątrz innej metody, aby zamknąć wszystkie pozycje:
1 2 3 4 | |
Tutaj self.get_bot_positions() wywołuje metodę pomocniczą, zwracając tylko pozycje powiązane z bieżącą etykietą bota.
Podobnie metoda get_distance_in_pips() może być ponownie wykorzystana do podejmowania decyzji handlowych. Na przykład w strategii siatki możesz chcieć otworzyć nowe zlecenie tylko wtedy, gdy rynek przesunął się wystarczająco daleko od ostatniej pozycji:
1 2 3 4 5 6 7 | |
Inne koncepcje
Przestrzenie nazw i importy
Przestrzenie nazw w Pythonie pomagają organizować kod i unikać kolizji nazw poprzez grupowanie powiązanych identyfikatorów (zmiennych, funkcji, klas). Importy pozwalają na wprowadzenie zewnętrznych modułów, bibliotek lub pakietów w celu rozszerzenia funkcjonalności poza standardowe możliwości Pythona.
W Pythonie możesz importować standardowe moduły lub niestandardowe pakiety:
1 2 | |
Możesz również importować określone funkcje lub klasy:
1 2 | |
Podczas pisania algorytmów dla cTrader w Pythonie importy działają nieco inaczej, ponieważ cTrader integruje się z opartym na .NET API cTrader Algo. Ta konfiguracja obejmuje mostek, który umożliwia kodowi Pythona interakcję z zestawami .NET, co wyjaśnia, dlaczego typowy cBot zaczyna się od:
1 2 3 4 5 6 7 8 9 | |
Gdzie:
import clrładuje Common Language Runtime (CLR), umożliwiając Pythonowi współpracę z bibliotekami .NET.clr.AddReference("cAlgo.API")odwołuje się do zestawu cAlgo API, który zawiera wszystkie klasy, metody i obiekty związane z handlem.from cAlgo.API import *wprowadza wszystkie typy z API (np.TradeType,Color,Position).from robot_wrapper import *ładuje funkcje pomocnicze i wrappery, które upraszczają typowe operacje handlowe.
System przestrzeni nazw zapewnia, że:
- Wbudowane nazwy Pythona (takie jak
print) unikają konfliktów z nazwami cTrader (takimi jakapi.Print). - Wszystkie obiekty specyficzne dla handlu (
api.Symbol,api.Indicators,api.ExecuteMarketOrder) pochodzą z przestrzeni nazw cTrader Algo API, utrzymując je zorganizowane i odrębne. - Możesz rozszerzyć funkcjonalność poprzez importowanie własnych niestandardowych pakietów, aby działały razem z wbudowanymi typami cTrader.
Pętle
Pętle pozwalają na powtarzanie operacji na sekwencji wartości lub do momentu spełnienia warunku. W handlu algorytmicznym pętle są często używane do przetwarzania pozycji (np. zamykania, filtrowania lub aktualizowania ich), sprawdzania warunków dla wielu aktywów lub wskaźników, implementowania strategii siatki lub martingale, gdzie wymagane jest powtarzalne składanie zleceń, i więcej.
W Pythonie iteracja jest prosta i obsługuje zarówno pętle for (do iterowania przez kolekcje), jak i pętle while (do powtarzania do momentu zmiany warunku).
Możesz napisać pętlę do zamykania pozycji:
1 2 3 4 | |
W tym przypadku:
self.get_bot_positions()zwraca wszystkie pozycje należące do bieżącego cBota.- Pętla
forprzechodzi przez każdą pozycję. - Pasujące pozycje są zamykane za pomocą
api.ClosePosition.
Rozważ inną pętlę, która iteruje po wszystkich otwartych pozycjach siatki, zamyka je jedną po drugiej i rekurencyjnie sprawdza, czy pozostały jakieś pozycje (zabezpieczenie na wypadek częściowych zamknięć).
1 2 3 4 5 6 | |
Instrukcje warunkowe
Instrukcje warunkowe kontrolują przepływ wykonania w Pythonie, umożliwiając algorytmowi podejmowanie decyzji na podstawie wyrażeń logicznych. Warunki są podstawą logiki strategii, określając, kiedy wejść, wyjść lub zarządzać pozycjami.
Python obsługuje trzy główne konstrukcje warunkowe:
if– wykonuje kod, gdy warunek jest prawdziwy.elif(else if) – sprawdza inny warunek, jeśli pierwszy był fałszywy.else– zapewnia rozwiązanie awaryjne, gdy żaden warunek nie został spełniony.
Rozważ warunki przecięcia MACD wyrażone w tym kodzie:
1 2 3 4 | |
Ta struktura:
- Składa zlecenie kupna, gdy linia MACD jest powyżej linii sygnału.
- Składa zlecenie sprzedaży, gdy linia MACD jest poniżej linii sygnału.
- Pomija handel, jeśli nie ma wyraźnego sygnału.
Listy
Python zapewnia potężne i zwięzłe narzędzia do pracy z kolekcjami danych, takimi jak transakcje, ceny lub wskaźniki. Dwa z najczęstszych to list comprehensions i wbudowane funkcje agregujące, takie jak sum().
Na przykład możesz napisać kod, który iteruje po numbers i zachowuje tylko liczby parzyste w ten sposób:
1 2 | |
Możesz użyć list comprehension, aby wybrać tylko pozycje dla bieżącego symbolu, tworząc przefiltrowaną listę, która jest przydatna w środowiskach wielosymbolowych.
1 | |
Agregowanie zysku lub wolumenu za pomocą sum() to standardowe podejście w strategiach handlu siatką do określania, kiedy całkowity zysk osiąga cel.
1 | |
Możesz połączyć filtrowanie i agregację w ten sposób:
1 2 | |
Operacje synchroniczne i asynchroniczne
Python domyślnie stosuje synchroniczny model wykonania. Metody cyklu życia Twojego algorytmu, takie jak on_start, on_tick i on_bar_closed, są wyzwalane przez pętlę zdarzeń platformy, jedna na raz.
Oto podstawowa reprezentacja synchronicznego przepływu handlowego:
graph TD
A(Wykrycie sygnału) ==> B(Wykonanie zlecenia)
B ==> C(Pozycja osiąga<br>TP/SL)
C ==> D(Zamknięcie pozycji)
D ==> A W przepływach synchronicznych każda długotrwała operacja może zablokować wątek, potencjalnie opóźniając następne zdarzenie. Jednak w rzeczywistych strategiach algorytmy zazwyczaj inicjują nieblokujące akcje, takie jak składanie zlecenia lub ustawianie stop loss i take profit, a następnie czekają na przyszłe zdarzenia (takie jak nowy tick lub słupek), aby obsłużyć wyniki. Ta konfiguracja skutkuje orkiestracją podobną do asynchronicznej, mimo że konstrukcje async/await Pythona nie są używane.
Uwaga
W przypadku większości algorytmów handlowych jawne programowanie asynchroniczne nie jest konieczne.
cTrader zarządza współbieżnością poprzez serializację wywołań zwrotnych opartych na zdarzeniach. Każda metoda jest wywoływana niezależnie i nigdy równolegle, eliminując potrzebę zabezpieczeń wielowątkowych. Ten projekt umożliwia strategiom reagowanie na wiele warunków handlowych jednocześnie, w sensie logicznym, bez blokowania.
W poniższym przykładzie strategia ocenia sygnały kupna i sprzedaży niezależnie i odpowiednio reaguje, bez żadnego nakładania się kontekstu wykonania.
graph TD
A([Wykrycie sygnału]) ==> B([Otwarcie<br>zlecenia kupna]) & C([Otwarcie zlecenia<br>sprzedaży jako<br>zabezpieczenia]) ==> D([Zlecenie osiąga<br>take profit lub<br>stop loss])
D ==> E([Zamknięcie pozycji])
E ==> A Mimo że decyzje mogą wydawać się równoległe, są obsługiwane sekwencyjnie przez wewnętrzny system kolejkowania cTrader. Architektura platformy ma na celu zapobieganie problemom ze współbieżnością, jednocześnie utrzymując responsywność robotów handlowych na zmiany rynkowe.
