22 December 2010

Forex - Casino - Gold

Forex jest grą, kasyno jej zasadami, a złoto nagrodą.
Jak generować pewne zyski - czyli strategia podwajania straconych pozycji.
Znajomy opowiedział mi jak gra w kasynie w ruletkę obstawiając tylko kolory czarny i czerwony, ale nigdy nie równoczaśnie. Stawia zakład na jeden kolor i jeśli nie trafi podwaja stawkę na tym kolorze. Efekt jest taki, że jego dochód z wieczora spędzonego w miłym towarzystwie, wynosi podwojoną stawkę z zakładów, które trafił za pierwszym razem. Strat nie generuje. A co jeśli braknie  pieniędzy na podwajanie ? Stawka początkowa musi być mała bo według jego doświadczeń, aż dziesięciokrotnie potrafi wypaść jeden kolor - i taki posiada zapas gotówki. Prosta i skuteczna strategia gry, do czasu, aż niewłaściwy kolor wypadnie jedenaści razy pod rząd, ale  według niego większe prawdopodobieństwo jest, że on trafi dziesięć razy odpowiedni kolor za pierwszym razem.
Jakiś czas temu pisałem na zamówienie skrypt dla MetaTreader'a 4. Skrypt jest robotem, którego zadaniem jest gra na parze EUR/USD. Strategia wymyślona przez zamawiającego, w odpowiednich warunkach, dawała 44% zysku, ale istniało ryzyko strat.
Po rozmowie z hazardzistą przetestowałem strategię z kasyna na rynku złota dla cen z okresu od 21.11.2010 do 19.12.2010 dla okresu M1 (modelling quality 25%) i H1 (modelling quality 90%).
Test przeprowadziłem dla trzech przypadków zlecień - BUY, SELL, BUY & SELL:

TYLKO "BUY"

zysk: 2800.58 euro (5,60 %)





zysk: 2794.37 euro (5,58 %)

TYLKO "SELL"

zysk 2336.69 euro (4,67 %) 



zysk  2336,87 euro (4,67 %)



"BUY & SELL" 
  
zysk 5330.27 euro (10,66 %)



zysk  5334,74 euro (10,66 %)



 W badanym okresie cena złota wzrosła o około 2%. Przyjęte strategie nie wymagają znajomości rynku i przewidywania ceny w wybranym okresie. Zysk jest zawsze, dopóki nie otrzymamy margin call'a i nie pojawią się problemy natury technicznej (brak dostępu do sieci lub zawieszenie systemu).
Poniżej przedstawiam algorytm strategii, która wygenerowała wykresy.
#property copyright "http://FiveWithFour.blogspot.com"
#property link "http://FiveWithFour.blogspot.com"

// parametry sterujące algorytmem

double dFirstLots = 0.1; // pierwsza stawka
int iSlippage = 1;
double dTakeProfitBUY =5 ; // skok - realizacji zysku dla BUY
double dLostProfitBUY = 5; // skok - podbicie stawki x 2
double dTakeProfitSELL = 5; // skok - realizacji zysku dla SELL
double dLostProfitSELL = 5; // skok - podbicie stawki x 2
string sSymbol = "GOLD";

// funkcja uruchamiająca działanie 

int init()
  {
  OrderSend(sSymbol, OP_BUY, dFirstLots, Ask , iSlippage, 0, 0, "Casino", 12345, 0 , CLR_NONE); // wystawienie zlecenia BUY
  OrderSend(sSymbol, OP_SELL, dFirstLots, Bid , iSlippage, 0, 0, "Casino", 12345, 0 , CLR_NONE); // wystawienie zlecenia SELL
  return(0);
  }
// funkcja algorytmu - uruchamiana przy zmianie ceny waloru
int start()
  {
  int i=0;
  int iTicket;
  double dLots, dOpnPrice;
  while(OrderSelect(i,SELECT_BY_POS))
    {
    iTicket = OrderTicket(); // znacznik transakcji
    dLots = OrderLots();
    dOpnPrice = OrderOpenPrice();
    switch (OrderType())
      {
      case OP_SELL:
        {
        if (dOpnPrice <= (Ask - dLostProfitSELL))
          {
          while ((OrderSend(sSymbol, OP_SELL, dLots*2, Bid , iSlippage, NULL, NULL, "Casino", 12345,0 , CLR_NONE) < 0))
            {
            if (GetLastError() == 134) // brak funduszy na dalsze zakłady 
              {
              Print("G A M E O V E R - L O O S E R ! ! ! ");
              break;
              } 
            }
            while (!(OrderClose(iTicket, dLots, Ask, 1, CLR_NONE)))
              {
              //Print("OP_SELL - OrderClose() error: ", GetLastError());
              }
            }
            if (dOpnPrice >= (Ask + dTakeProfitSELL)) // realizacja zysku z opcji OP_SELL i otwarcie nowej pozycji
              {
              while (!(OrderClose(iTicket, dLots, Ask, 1, CLR_NONE)))
                {
                //Print("OP_SELL - OrderClose() error: ", GetLastError());
                }
              while ((OrderSend(sSymbol, OP_SELL, dFirstLots, Bid , iSlippage, NULL, NULL, "Casino",12345,0 , CLR_NONE) < 0))
                {
                if (GetLastError() == 134) // brak funduszy na dalsze zakłady
                  {
                  Print("G A M E O V E R - L O O S E R ! ! ! ");
                  break;
                  } 
                } 
              }
              break;
            } 
      case OP_BUY:
        {
        if (dOpnPrice >= (Bid + dLostProfitBUY))
          {
          while ((OrderSend(sSymbol, OP_BUY, dLots*2, Ask, iSlippage, NULL, NULL, "Casino",12345, 0, CLR_NONE) < 0))
            {
            if (GetLastError() == 134) // brak funduszy na dalsze zakłady
              {
              Print("G A M E O V E R - L O O S E R ! ! ! ");
              break;
              }
            }
            while (!(OrderClose(iTicket, dLots, Bid, 1, CLR_NONE)))
              {
              //Print("OP_BUY - OrderClose() error: ", GetLastError());
              }
            }
            if (dOpnPrice <= (Bid - dTakeProfitBUY)) // realizacja zysku z opcji OP_BUY i otwarcie nowej pozycji
              {
              while (!(OrderClose(iTicket, dLots, Bid, 1, CLR_NONE)))
                {
                //Print("OP_BUY - OrderClose() error: ", GetLastError());
                }
                while ((OrderSend(sSymbol, OP_BUY, dFirstLots, Ask ,iSlippage, NULL, NULL, "Casino", 12345, 0, CLR_NONE) < 0))
                  {
                  if (GetLastError() == 134) // brak funduszy na dalsze zakłady
                    {
                    Print("G A M E O V E R - L O O S E R ! ! ! ");
                    break;
                    }
                  //Print("OP_BUY - OrderSend() error: ", GetLastError());
                  } 
                } 
                break;
              }
            } 
            i++;
          }
          return(0);
  }
Logika algorytmu działa poprawnie. Problemy mogą wystąpić przy obsłudze operacji - jednak nie rozwijałem jej ze względu na czytelność kodu. Algorytm jest skalowany poprzez parametry sterujące. Koncepcja jest prosta i może być wstępem do optymalizacji kodu aby przynosił większe zyski.
zysk 16420,40 (32,84 %) 
 
 zysk 16416,58 euro (32,83 %) 
 
 Zapraszam do zabawy kodem.