Przejdź do treści

Grid cBot

Przegląd strategii

Grid cBot implementuje strategię handlu siatką, w której wiele zleceń kupna lub sprzedaży dla symbolu jest składanych w regularnych odstępach cenowych lub „krokach", tworząc „siatkę" pozycji. Gdy cena symbolu się zmienia, nowe pozycje są stale otwierane, aby wykorzystać wahania.

Grid cBot wykorzystuje kombinację prostej arytmetyki i kontroli logicznych do otwierania pozycji, obliczania zysków i zarządzania swoimi operacjami handlowymi. Jest najbardziej skuteczny na rynkach ograniczonych zakresem lub poruszających się w bok. Dobrze radzi sobie również w warunkach niskiej zmienności oraz na rynkach ze znanymi poziomami oporu i wsparcia.

Tworzenie cBota

Dowiedz się, jak tworzyć cBoty, używając C# lub Pythona, w naszych szczegółowych przewodnikach.

Kod Grid cBota jest dostępny w naszych publicznych repozytoriach C# i Python. Ten sam kod jest dostępny jako szablon w kreatorze tworzenia algorytmów w aplikacji cTrader Windows lub Mac, lub możesz po prostu skopiować i użyć poniższego fragmentu kodu:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None)]
    public class Grid : Robot
    {
        [Parameter("Volume (lots)", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]
        public double VolumeInLots { get; set; }

        [Parameter("Trade Side")]
        public TradeType TradeType { get; set; }

        [Parameter("Step (pips)", DefaultValue = 5, MinValue = 0.1, Step = 0.1)]
        public double StepPips { get; set; }

        [Parameter("Target Profit", DefaultValue = 20)]
        public double TargetProfit { get; set; }

        private bool enoughMoney = true;

        protected override void OnStart()
        {
            if (GridPositions.Length == 0)
                OpenPosition();
        }

        protected override void OnTick()
        {
            if (GridPositions.Sum(p => p.NetProfit) >= TargetProfit)
            {
                Print("Target profit is reached. Closing all grid positions");
                CloseGridPositions();
                Print("All grid positions are closed. Stopping cBot");
                Stop();
            }
            if (GridPositions.Length > 0 && enoughMoney)
            {
                var lastGridPosition = GridPositions.OrderBy(p => p.Pips).Last();
                var distance = CalculateDistanceInPips(lastGridPosition);

                if (distance >= StepPips)
                    OpenPosition();
            }
        }

        private Position[] GridPositions
        {
            get
            {
                return Positions
                    .Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType)
                    .ToArray();
            }
        }

        private double CalculateDistanceInPips(Position position)
        {
            if (position.TradeType == TradeType.Buy)
                return (position.EntryPrice - Symbol.Ask) / Symbol.PipSize;
            else
                return (Symbol.Bid - position.EntryPrice) / Symbol.PipSize;
        }

        private void OpenPosition()
        {
            var result = ExecuteMarketOrder(TradeType, SymbolName, Symbol.QuantityToVolumeInUnits(VolumeInLots), "Grid");
            if (result.Error == ErrorCode.NoMoney)
            {
                enoughMoney = false;
                Print("Not enough money to open additional positions");
            }
        }

        private void CloseGridPositions()
        {
            while (GridPositions.Length > 0)
            {
                foreach (var position in GridPositions)
                {
                    ClosePosition(position);
                }
            }
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *

# Import trading wrapper functions
from robot_wrapper import *

class GridSample():
    def on_start(self):
        self.volumeInUnits = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.enoughMoney = True
        if len(self.get_grid_positions()) == 0:
            self.open_position()

    def on_tick(self):
        grid_positions = self.get_grid_positions()
        net_profit_sum = sum([p.NetProfit for p in grid_positions])
        if net_profit_sum >= api.TargetProfit:
            api.Print("Target profit is reached. Closing all grid positions")
            self.close_grid_positions()
            api.Print("All grid positions are closed. Stopping cBot")
            api.Stop()

        if len(grid_positions) > 0 and self.enoughMoney == True:
            position_with_highest_pips = sorted(grid_positions, key=lambda pos: pos.Pips, reverse=True)[0]
            distance = self.get_distance_in_pips(position_with_highest_pips)          
            if distance >= api.StepPips:
                self.open_position()

    def get_grid_positions(self):
        return [pos for pos in api.Positions if pos.SymbolName == api.SymbolName and pos.TradeType == api.TradeType]

    def open_position(self):
        result = api.ExecuteMarketOrder(api.TradeType, api.SymbolName, self.volumeInUnits, "Grid")
        if result.Error == ErrorCode.NoMoney:
            self.enoughMoney = False
            api.Print("Not enough money to open additional positions")

    def close_grid_positions(self):
        for position in self.get_grid_positions():
            position.Close()

        if len(self.get_grid_positions()) > 0:
            self.close_grid_positions()

    def get_distance_in_pips(self, position):
        return (position.EntryPrice - api.Symbol.Ask if position.TradeType == TradeType.Buy else api.Symbol.Bid - position.EntryPrice) / api.Symbol.PipSize

Integracja wskaźnika

Grid cBot nie polega na żadnym wskaźniku do zdefiniowania swojej strategii siatki; nie próbuje przewidzieć, czy cena symbolu wzrośnie, czy spadnie. Zamiast tego celuje w zyskowne transakcje z ruchów cenowych w dowolnym kierunku.

cBot wykonuje transakcje na podstawie tej prostej zasady: Jeśli cena symbolu przesunie się poza określoną liczbę pipsów (zdefiniowaną przez parametr StepPips), cBot otwiera nową pozycję.

Obliczenia i logika

Początkowa realizacja transakcji

Gdy cBot się uruchamia, sprawdza, czy w siatce są jakieś otwarte pozycje. Jeśli nie ma otwartych pozycji, cBot natychmiast otwiera pierwszą pozycję za pomocą metody OpenPosition(). Ten pierwszy krok zapewnia, że siatka rozpoczyna się od początkowej transakcji na podstawie określonej strony transakcji (TradeType).

Monitorowanie zysku

Przy każdym ticku (na przykład, każdej aktualizacji ceny), cBot sprawdza, czy skumulowany zysk netto wszystkich otwartych pozycji siatki osiąga lub przekracza określony zysk docelowy (TargetProfit). Jeśli zysk docelowy został osiągnięty, wszystkie otwarte pozycje są zamykane, a cBot przestaje działać.

Zysk docelowy to suma zysku netto z każdej pozycji w siatce.

\[ \text{Total net profit} = \sum_{i=1}^{n} \text{NetProfit}(p_i) \]

\(n\) – liczba otwartych pozycji w siatce

\(\text{NetProfit}(p_i)\) – zysk netto pozycji \(i\)

Otwieranie pozycji

Jeśli zysk docelowy nie został osiągnięty i są otwarte pozycje, cBot oblicza odległość (w pipsach) między ostatnio otwartą pozycją siatki a bieżącą ceną rynkową.

Dla pozycji kupna:

\[ D_b = \frac{P_e - P_a}{S} \]

Dla pozycji sprzedaży:

\[ D_s = \frac{P_b - P_e}{S} \]

\(D_b\) – odległość w pipsach między ceną wejścia a bieżącą ceną ask.

\(D_s\) – odległość w pipsach między bieżącą ceną bid a ceną wejścia.

\(P_e\) – cena, po której ostatnia pozycja kupna dla symbolu została otwarta.

\(P_a\) – bieżąca cena ask dla symbolu.

\(P_b\) – bieżąca cena bid dla symbolu.

\(S\) – wartość jednego pipsa dla symbolu.

Jeśli obliczona odległość jest większa lub równa zdefiniowanemu rozmiarowi kroku (StepPips), nowa pozycja jest otwierana za pomocą metody OpenPosition().

Za każdym razem przed otwarciem nowej pozycji, cBot sprawdza i potwierdza, że są wystarczające środki na operację. Jeśli środki są niewystarczające, cBot przestaje próbować otwierać nowe pozycje i loguje komunikat „Not enough money to open additional positions".

Zamykanie pozycji

Gdy TargetProfit zostanie osiągnięty, cBot loguje komunikat „Target profit is reached. Closing all grid positions".

Metoda CloseGridPositions() następnie przechodzi przez wszystkie otwarte pozycje w siatce, zamyka je, a następnie cBot loguje komunikat „All grid positions are closed. Zatrzymywanie cBota" komunikat. cBot zostaje następnie zatrzymany.

Parametry

Parametr Jednostka Definicja Wskazówki
Ilość Lot Wolumen każdej transakcji. Konserwatywni traderzy mogą określić małe rozmiary lotów, aby zmniejszyć ekspozycję i ostrożnie zarządzać ryzykiem, szczególnie na niestabilnym rynku. W ten sposób każda potencjalna strata jest minimalizowana, jeśli rynek porusza się wbrew gridowi.

Agresywni traderzy mogą określić duże rozmiary lotów, aby zmaksymalizować zyski, gdy są pewni rynku. Chociaż to podejście jest bardziej ryzykowne, zapewnia większe zyski, gdy grid skutecznie wychwytuje duże wahania cen.
Strona transakcji — Kierunek transakcji (kupno lub sprzedaż). Na rosnącym rynku traderzy mogą wybrać kupno. Gdy symbol tymczasowo cofa się w dół, cBot kupuje na niższych poziomach. Gdy rynek wraca w górę, każda pozycja kupna staje się rentowna.

Na spadającym rynku traderzy mogą wybrać sprzedaż. Gdy cena symbolu tymczasowo cofa się w górę, cBot sprzedaje na wyższych poziomach. Gdy rynek wraca w dół, każda pozycja sprzedaży staje się rentowna.
Krok Pip Odległość między dwiema kolejnymi pozycjami gridu. Im mniejszy krok, tym częściej otwierane są nowe transakcje, podczas gdy większy krok skutkuje mniejszą liczbą transakcji. Na rynku bocznym lub o niskiej zmienności traderzy mogą ustawić małą wartość. To ustawienie zapewnia, że cBot otwiera pozycje częściej i wychwytuje małe wahania cen, szczególnie gdy cena porusza się w wąskim paśmie.

Na rynkach trendowych lub bardziej zmiennych traderzy mogą ustawić dużą wartość. To ustawienie zmniejsza liczbę otwieranych transakcji, pozwala cBotowi wychwytywać większe ruchy i pomaga uniknąć nadmiernego handlu podczas silnych trendów.
Docelowy zysk — Skumulowany zysk w walucie konta, który musi zostać osiągnięty, zanim cBot zamknie wszystkie otwarte pozycje i zatrzyma handel. Traderzy szukający szybkich, małych zysków mogą ustawić niską wartość. To ustawienie zapewnia, że grid zamyka się, gdy tylko zostanie osiągnięty niewielki zysk, minimalizując ryzyko zbyt długiego utrzymywania pozycji na niestabilnych rynkach.

Traderzy, którzy wolą czekać na duże zyski, mogą ustawić wysoką wartość. To ustawienie pozwala gridowi pozostać otwartym dłużej, umożliwiając cBotowi gromadzenie zysków w serii większych ruchów rynkowych, zanim wszystkie pozycje zostaną zamknięte.

Aplikacja

Rynki ograniczone zakresem lub boczne

Grid cBot jest najbardziej skuteczny na rynkach ograniczonych zakresem, gdzie cena oscyluje między poziomami wsparcia i oporu. Na takich rynkach, gdy ceny często poruszają się w górę i w dół w określonym zakresie, cBot regularnie otwiera pozycje i wykorzystuje wahania.

Przypadek użycia

Rozważmy scenariusz, w którym EURUSD pozostaje w zakresie między 1,1000 a 1,1100. cBot otwiera pozycje kupna, gdy cena spada bliżej 1,1000 i otwiera pozycje sprzedaży w pobliżu 1,1100. Gdy cena oscyluje między tymi poziomami, cBot uzyskuje zyski z każdego wahania.

Najlepsze praktyki

  • Ustaw mały rozmiar kroku, aby wychwytywać częste wahania cen.
  • Ustaw umiarkowany docelowy zysk, aby grid zamykał się często, pozwalając Ci zabezpieczyć małe, stałe zyski.
  • Monitoruj wiadomości rynkowe lub nadchodzące wydarzenia, które mogą prowadzić do przełamania zakresu i spowodować duże spadki.

Rynki o niskiej zmienności

Na rynkach o niskiej zmienności ruchy cen są zazwyczaj powolne i mniej wyraźne. Gdy cena porusza się stopniowo, Grid cBot ma wystarczająco dużo czasu, aby otworzyć wiele pozycji bez ryzyka dużych, gwałtownych ruchów rynkowych.

Przypadek użycia

Rozważmy scenariusz, w którym USDJPY wykazuje niską zmienność, jak to często bywa podczas azjatyckiej sesji handlowej. Grid cBot może otwierać pozycje z małym rozmiarem kroku i wychwytywać małe, stopniowe ruchy cen, które występują w tych spokojnych godzinach.

Najlepsze praktyki

  • Użyj ciasnego rozmiaru kroku, aby wykorzystać mniejsze ruchy cen typowe dla rynków o niskiej zmienności.
  • Ustaw niski wolumen transakcji, aby zmniejszyć ryzyko w przypadku nieoczekiwanego wzrostu zmienności.
  • Obserwuj warunki rynkowe, nieoczekiwane wiadomości lub wydarzenia i bądź gotowy do szybkiego zatrzymania cBota.

Rynki ze znanymi poziomami

Grid cBot może dobrze radzić sobie na rynkach z silnymi, dobrze zdefiniowanymi poziomami wsparcia i oporu. Te poziomy działają jako bariery cenowe i powodują, że rynek często odbija się, tworząc zakres, który cBot może wykorzystać.

Przypadek użycia

Rozważmy scenariusz, w którym cena złota (XAUUSD) oscyluje między silnym poziomem wsparcia na 2000 USD a poziomem oporu na 2050 USD. Grid cBot otwiera zlecenia kupna w pobliżu 2000 USD i zlecenia sprzedaży w pobliżu 2050 USD, czerpiąc zyski z odbijania się ceny między tymi poziomami.

Najlepsze praktyki

  • Ustaw rozmiar kroku w oparciu o zmienność rynku. Rynek o wysokiej zmienności może wymagać większych rozmiarów kroków, podczas gdy rynki o niskiej zmienności mogą używać mniejszych kroków.
  • Używaj Grid cBot na rynkach z dobrze ustalonymi poziomami wsparcia i oporu, aby uniknąć złapania w przełamanie.
  • Zachowaj ostrożność w przypadku wydarzeń lub wiadomości, które mogą spowodować przełamanie, aby uniknąć dużych strat. cBot nie jest przygotowany do obsługi sytuacji, gdy rynek przebija poziomy wsparcia lub oporu.

Rynki bezkierunkowe

Niektóre pary walutowe wykazują ruch bezkierunkowy z częstymi wahaniami cen, ale ich cena nie wykazuje silnego długoterminowego trendu. Grid cBot dobrze sprawdza się na takich rynkach, ponieważ może wychwytywać częste wahania bez ryzyka uwięzienia w długoterminowym trendzie.

Przypadek użycia

Rozważmy scenariusz, w którym EURCHF porusza się w sposób bezkierunkowy, co jest częstym zjawiskiem ze względu na stabilność gospodarki strefy euro i Szwajcarii. Grid cBot może otwierać pozycje z małym rozmiarem kroku, wychwytując zyski z częstych wahań bez obaw o duże trendy kierunkowe.

Najlepsze praktyki

  • Użyj małego rozmiaru kroku, aby wychwytywać częste ruchy cenowe.
  • Rozważ ustawienie niskiego wolumenu transakcji, aby zarządzać ryzykiem w przypadku, gdy rynek przejdzie w trend.

Podsumowanie

Grid cBot działa przy założeniu, że zarówno podczas rynków zwyżkujących, jak i spadkowych będą występować zniesienia lub cofnięcia. Kupuje tanio i sprzedaje drogo na rynkach zwyżkujących oraz sprzedaje drogo i kupuje tanio na rynkach spadkowych; cBot wychwytuje zyski, gdy rynek wznawia główny trend po zniesieniach.

Ponieważ cBot nie używa wskaźników, nie może ocenić, czy rynek jest w trendzie, czy w konsolidacji. Po prostu otwiera pozycje wyłącznie na podstawie ruchu ceny, ignorując nastroje rynkowe lub siłę trendu.

Brak wskaźników sprawia, że proces handlowy jest czysto mechaniczny; cBot opiera się wyłącznie na predefiniowanych regułach otwierania pozycji w regularnych odstępach czasu. Chociaż takie podejście może być opłacalne na rynkach w konsolidacji, zwykle przynosi straty na rynkach trendowych, wysoce zmiennych lub szybko zmieniających się.

Oprócz skonfigurowania cBota w celu zastosowania własnych strategii, traderzy mogą rozważyć wprowadzenie wskaźników do filtrowania transakcji w oparciu o warunki rynkowe:

  • Moving Averages (MA) mogą pomóc w identyfikacji trendu rynkowego, umożliwiając cBotowi handel wyłącznie w kierunku trendu.
  • Relative Strength Index (RSI) może sygnalizować warunki wykupienia lub wyprzedania, pomagając cBotowi unikać otwierania nowych pozycji, gdy rynek jest nadmiernie rozciągnięty w jednym kierunku.
  • Bollinger Bands mogą dostarczyć informacji o zmienności cen, umożliwiając cBotowi dostosowanie odstępów siatki lub wstrzymanie handlu w okresach wysokiej zmienności.