Proiectarea Si Realizarea Unui Produs Software de Tranzactionare Automatizata pe Piata Valutara

INTRODUCERE

CAP. I Piata valutara: Prezentare generala

Piata valutara internationala

Cotatii de pret

Termeni si conditii

Tipuri de ordine

Lumanarile japoneze

CAP. II Platforma de tranzactionare MT4 si limbajul de programare MQL4

2.1 MetaTrader 4 – Platforma de tranzactionare online

2.2 MQL4 – Limbaj de programare

2.2.1 Notiunea de control

2.2.2 Functii speciale

2.2.3 Structura unui program

CAP. III Proiectarea de detaliu a aplicatiei

3.1 Definirea obiectivelor aplicatiei informatice

3.2 Strategia de tranzactionare folosita

3.3 Diagrama de flux a datelor/ structura aplicatiei

3.3.1Date de intrare

3.3.2 Prelucrarea datelor

3.3.3 Date de iesire

3.3.4 Structura apliatiei dupa cum reiese din Diagrama de flux

3.4 Nivel 1: Calcul valori indicatori

3.4.1 Indicatorul nivelelor de suport si rezistenta

3.4.1.1 Prezentare generala a indicatorului

3.4.1.2 Algoritmul indicatorului

3.4.1.3 Criterii de eficienta/ structuri de date

3.4.1.4 Proiectarea principalelor functii

3.4.2 Indicatorul Stochastic

3.5 Nivel 2: Criterii de tranzactionare

3.6 Nivel 3: Calcul atribute comanda

3.7 Nivel 4: Trimiterea comenzilor catre terminal

CAP. IV Prezentarea aplicatiei

4.1 Instalarea aplicatiei automatizate de tranzactionare pe piata valutara

4.2 Rularea aplicatiei automatizate de tranzactionare pe piata valutara

4.3 Meniul de configurare a aplicatiei

4.4 Optimizarea si testarea aplicatiei

4.4.1 Folosirea StrategyTester in vederea optimizarii si testarii aplicatiei

4.4.2 Parametrizarea aplicatiei

4.4.3 Testarea Expert-Advisorului – rezultatele obtinute de aplicatie pe date de test

4.4.4 Interpretarea performantei aplicatiei pe date de test

4.5 Concluzii privind eficienta aplicatiei automatizate de tranzactionare

ANEXE:

3.1 Licenta.mq4

3.2 CriteriiTranzactionare.mqh

3.3 Support&Resistance.mqh

3.4 PlasareComenzi.mqh

4.1 Rezultatele Optimizarii USD/CHF

4.3 Rezultatele testelor USD/CAD

BIBLIOGRAFIE

INTRODUCERE

Principiile fundamentale ale tranzactionarii la bursa nu s-au schimbat de sute de ani, dar mediul bursei moderne difera foarte mult de cel al anilor 80. Tranzactionare electronica a transformat pietele, facandu-le mai accesibile ca niciodata. Accesul direct la bursa (Direct Market Access – DMA) si tranzactionarea automatizata a conferit investitorilor mai mult control asupra modului in care strategiile lor sunt executate. Astfel, DMA permite investitorului sa isi trimita comenzile direct la bursa, folosind infrastructura unui broker.

Pentru a genera un rezultat pozitiv din tranzactionare, investitorul are nevoie de o strategie, sa stie cand si cum sa plaseze si sa inchida comenzile pentru a putea genera profit. De aceea se impune folosirea unui sistem de tranzactionare care sa fundamenteze orice decizie de vanzare-cumparare.

Un sistem de tranzactionare reprezinta un set de reguli pe care traderii le folosesc pentru a determina intrarile si iesirile dintr-o pozitie. Dezvoltarea si folosirea de sisteme de trading pot ajuta traderii sa obtina venituri consistente, limitand riscurile.

Sistemele automatizate de tranzactionare sunt create prin conversia regulilor unui sistem de tranzactionare in cod. Calculatorul executa aplicatia software cautand ocazii de a tranzactiona care sa respecte regulile sistemului. In final, comenzile sunt plasate automat catre broker.

Sistemele automatizate de tranzactionare sunt folosite de bancile de investitii, fondurile de pensii si alti investitori institutionali, precum si de investitorii persoane fizice. O treime din volumul de tranzactii efectuate in anul 2006 in Uniunea Europeana si Statele Unite au fost facute prin sisteme automatizate de tranzactionare, conform unor estimari facute de firma de cercetare si consultanta a industriei serviciilor financiare Aite Group.

In aceasta lucrare ne vom axa pe crearea unui sistem automatizat de tranzactionare pentru piata valutara (FOREX). In ultimii ani se remarca o crestere a cererii pentru asftel de produse software din partea investitorilor retail. Ca dovada avem aparitia marketplace-urilor de programe automatizate de tranzactionare integrate in platforme si oferta mare de astfel de programe din partea firmelor specializate in domeniu si a dezvoltatorilor independenti.

Obiectivul acestei lucrari de licenta este crearea unui produs software, un sistem automatizat de tranzactionare dezvoltat in limbajul de programare MQL4, pentru a fi utilizat in cadrul platformei de tranzactionare Meta Trader 4. Platforma MT4 este cea mai raspandita pentru tranzactionare online retail Forex Spot. Produsul software rezultat poate fi folosit atat pentru uz propriu de catre investitor, cat si pentru comercializarea acestuia pe marketplace-ul integrat in platforma MT4 sau comercializarea independent de platforma.

CAPITOLUL I: PIATA VALUTARA

1.1 Piata valutara internationala

Piața valutară internațională sau FOREX este locul unde valutele sunt cotate și convertite.

Forex este cea mai mare și lichidă piață financiară din lume. Volumul zilnic mediu depășește 4

trilioane USD și este în continuă creștere. O piață lichidă este piața în care participanții pot executa rapid tranzacții cu volum mare și impact redus asupra prețurilor, și pot intra sau ieși cu ușurință din tranzacții.

Nu există o locatie fixă pentru piata valutară, tranzacțiile se efectuează electronic și continuu 24h/zi cu excepția weekend-ului. Din acest motiv Forex este o piață Over the-counter sau off-exchange.

Cel mai mare centru financiar este Londra cu peste 30% din volumul global tranzacționat.

Piata valutară modernă s-a format la inceputul anilor 1970 când țările au trecut gradual la cursuri

de schimb flotante.

Toti participanții au acces la același preț în orice moment din orice punct al lumii. Cei mai importanți participanți sunt bancile centrale, băncile comerciale, fondurile de investiții, hedge fondurile, companii private, guverne și investitori individuali.

Băncile Centrale, ca Rezerva Federală (FED), Banca Centrala Europeană (ECB), Banca Angliei (BOE), etc. joaca un rol important în piata valutară. Ei participa in piață pentru a servi intereselor naționale, pentru a controla masa monetara, inflația sau/și ratele dobanzilor. Cand o banca centrală cumpără sau vinde valută scopul este acela de a stabiliza cursul de schimb al țării respective.

Bancile comerciale joaca 2 roluri in piata FOREX: facilitează tranzacțiile între 2 parti, cum ar fi companiile ce doresc sa schimbe valute, sau speculează prin cumpararea sau vanzarea lor.

Tranzacțiile se efectuează întotdeauna in pereche, unde o valută este cumparată sau vanduta pentru alta, un trader va cumpăra valuta ce se anticipează că o crească in valoare, sau va vinde valuta ce se anticipează ca o sa scadă față de cealalta.

Cele mai tranzactionate valute sunt:

USD United States Dollar

EUR Euro

JPY Japan Yen

GBP Great Britain Pound

CHF Switzerland Franc

CAD Canada Dollar

AUD Australia Dollar

NZD New Zealand Dollar

1.2 Cotatiile valutare

Când o valută este cotată, este raportată la alta valută, astfel că valoarea uneia este reflectată prin valoarea celeilalte.

Pretul, determinat de cerere si oferta, este influentat de multi factori, incluzand ratele dobanzilor, performantele economice, sentimentul privind asteptarile politice si sociale, cat si perceptia asupra performantelor din viitor ale unei valute fata de alta.

1.3 Termeni și condiții

Bid, Ask

Exista intotdeauna un pret bid – cerut si un pret ask – oferit pe toate cotatiile pietei Forex sipretul bid va fi intotdeauna mai mic decat pretul ask.

Pretul bid este utilizat la vanzarea unei perechi valutare (poziție short) și reflectă cât din valuta cotată se va obține la vânzarea unei unități din valuta de bază.

Prețul ask este utilizat la cumpărarea unei perechi valutare (poziție long) și reflectă cantitatea din valuta cotată ce trebuie plătită pentru a cumpăra o unitate valută de bază.

Spread

Diferența dintre prețul bid – de vânzare și prețul ask – de cumpărare se numește spread. Pentru Eur/Usd = 1.4915/1.4917 spread-ul este de 2.0 pips sau puncte.

PIP

Pip-ul este cea mai mica modificare pentru orice pereche valutară, sau pasul minim de cotare. Pentru majoritatea valutelor un pip este 0.0001. Pentru yenul japonez un pip este 0.01, pentru că această valută este cotată cu 2 zecimale.

Lot

Perechile valutare sunt tranzacționate de obicei în loturi. 100.000 unități monetare din valuta de bază reprezintă volumul standard pentru 1 lot, pentru un Mini lot (0.1 lots) standardul este de 10.000, iar pentru Micro lot (0.01 lots) 1000.

Leverage – Levier

Pentru a tranzacționa aceste sume mari brokerii oferă tranzacționare prin efect de levier.

Brokerul solicită o anumită sumă minimă în contul de tranzacționare, numită marjă inițială –

account margin sau initial margin.

În cazul în care fondurile din cont scad sub cerințele minime de marjă, brokerul va închide automat toate sau o parte din pozițiile deschise. Aceasta este o protecție a contului pentru a nu ajunge la o balanță negativă.

1.4 Tipuri de Ordine

Cumpărarea sau vânzarea la prețul curent se numește ordin la piață – market order sau instant execution.

Cumpărarea sau vânzarea la un anumit preț, diferit de prețul curent se numește ordin deplasat în timp sau ordin în așteptare – pending order. Ordinele Pending sunt:

Ordine Limită – Limit Orders și Ordine Stop – Stop Orders.

Ordinele limită și stop sunt ordine date brokerului pentru a cumpăra sau vinde loturi de valute la un preț specificat în viitor.

Vânzarea de la un preț mai mare decât cel actual este un Ordin Sell Limit, iar de la un preț mai mic Sell Stop. Cumpărarea de la un preț mai mic decăt cel actual este un Ordin Buy Limit, iar de la un preț mai mare Buy Stop.

Stop Loss este un Ordin pentru închiderea unei Poziții Deschise la un nivel specificat în cazul în care prețul evoluează în direcția nefavorabilă, pentru a preveni pierderi mai mari. Un ordin stop loss este valid până când poziția este lichidată sau anulată.

Take Profit este un Ordin de închidere a unei Poziții Deschise la un nivel specificat în cazul în care prețul evoluează în direcția favorabilă.

1.5 Lumânarile japoneze (candlestick )

Lumânarile japoneze reprezinta un mijloc stravechi si cel mai folosit de catre profesionisti pentru a reflecta fluctuatiile pietei. Au fost folosite pentru prima data de Munehis Homm în secolul XVI. Acesta era un renumit comerciant de orez si a observat ca poate previziona usor miscarea preturilor, urmarind perioadele precedente. Homm a atras atentia asupra repetarii acestor figuri (imagini), le-a analizat si ulterior a tranzactionat profitabil. Astazi lumânarile japoneze reprezinta una dintre cele mai folosite metode de analiza a evolutiei pietei. În esenta, acestea se aseamana cu graficele de bare, dar, spre deosebire de ele, lumânarile japoneze exprima directiile trendului prin diferite culori. Lumânarea bullish, de regula, este verde sau alba, iar cea bearish — rosie sau neagra (figura 1.1 ). În primul caz, distanta de la pretul de închidere pâna la pretul maxim se numeste umbra de sus, iar distanta de la pretul de deschidere pâna la pretul minim — umbra de jos. O situatie similara este si pentru lumânarea bearish.

Figura 1.1

CAPITOLUL II: Platforma de tranzactionare MT4 si limbajul de programare MQL4

2.1 MetaTrader 4 – Platforma de tranzactionare online

MetaTrader 4, cunoscuta si sub denumirea MT4, este o platforma de tranzactionare electronica utilizata pe scara larga de catre investitoriide tip retail pe piata valutara. Aceasta a fost dezvoltata de MetaQuotes Software si lansata in anul 2005.

Software-ul este licentiat pentru brokeri care ofera software-ul la clientii lor. MT4 consta dintr-o componenta server si o componenta client. Componenta server este rulata si gestionata de broker, iar software-ul client este furnizat clientilor broker-ului, care il folosesc pentru a avea acces la cotatii si grafice live, pentru a plasa comenzi si a-si gestiona conturile.

Clientul este o aplicatie Microsoft-Windows, care a devenit populara in principal datorita posibilitatii utilizatorilor finali de a crea propriile scripturi si roboti pentru tranzactionare automatizata.

Terminalul client include mediul informational, un set de parametri cu informatii despre starea pietei si cu privire la raporturile dintre un trader si un dealing center. Acesti parametri includ informatii despre preturile curente, limitari cu privire la dimensiunea minima si maxima a comenzilor, distanta minima de ordine de stop, precum si multi alti parametri utili care caracterizeaza starea actuala.

Mediul informational este actualizat atunci cand noi Tick-uri sunt primite de catre terminalul client din partea server-ului. (figura 2.1)

Notiunea de Tick

Un tick este un eveniment care reprezinta cea mai mica modificare a pretului unui simbol (perechi valutare) – un Tick contine pretul nou al unui simbol si timpul la care a fost inregistrata noua cotatie.

Tick-urile sunt transmise catre terminalul client de un server instalat intr-un dealing center. In functie de starea pietei, Tick-urile pot fi receptionate mai mult sau mai putin frecvent, dar fiecare dintre ele aduce o noua cotatie.

Figura 2.1

2.2 MQL4 – Limbaj de programare

Sistemele automatizate de tranzactionare sunt rulate din cadrul terminalului, acesta jucand si rolul de interfata grafica. MetaQuotes Language 4 (MQL4) este un limbaj integrat de programare pentru platforma MT4. Folosind acest limbaj, se pot crea indicatori, scripturi si programe de tranzactionare automatizata (EA) pentru a fi rulate in cadrul terminalului. MQL4 conține un număr mare de funcții necesare pentru preluarea si analiza de cotatii curente și primite anterior, precum si functii de management a comenzilor si controlul acestora. Editorul de text MetaEditor este folosit pentru scrierea codului.

2.2.1. Notiunea de control

Control este termenul folosit pentru a vorbi despre fluxul de executare a codului unui program, precum si fluxul dintre program si terminalul client.

Control este procesul de executare a actiunilor fixate de algoritmul programului si functiile terminalului client. Controlul poate fi transferat in interiorul programului de la o linie de cod la alta, precum si de la program catre terminalul client.

Inaintea lansarea programului, controlul este detinut de catre terminalul client. Odata ce programul este lansat si un nou Tick este primit, terminalul client transfera controlul catre program.

Terminalul client nu isi opreste functionarea dupa ce a cedat controlul catre program. Acesta continua sa lucreze la performanta maxima pe parcursul intregii perioade de timp cat este rulat pe PC. Programul poate incepe sa functioneze numai in cazul in care controlul i-a fost transferat de catre terminalul client.

Dupa ce a terminat functionarea, programul returneaza controlul la terminalul client. Atata timp cat programul detine controlul, acesta decide cand sa returneze controlul terminalului.

2.2.2. Functii speciale

O trasatura distincta a programelor automatizate de tranzactionare scrise in MQL4 este necesitatea lucrului cu informatii actualizate in mod constant in timp real. Aceasta particularitate se reflecta in forma functiilor speciale: OnInit(), OnDeinit(), OnTick().

Principala proprietate a functiilor speciale este executia acestora in cadrul unui program fara a avea un apel la functie din partea programului. Functiile speciale sunt apelate de terminalul client. Daca programul contine descrierea unei functii speciale, aceasta va fi apelata si executata in concordanta cu conditiile in care a fost apelata.

Functia speciala OnInit()

Proprietatea distincta a functie speciale OnInit() este executarea acesteia la initializarea programului. Daca un program contine descrierea functiei OnInit(), aceasta va fi apelata si executata in urmatoarele conditii:

dupa initializarea terminalului si actualizarea mediului informational

dupa recompilarea programului in MetaEditor

dupa schimbarea unui parametru de intrare a programului

Daca funtia OnInit() lipseste din program, nu se va face nici o actiune la pornirea programului.

Functia speciala OnTick()

Intr-un EA, OnTick() este apelat (si executat) imediat dupa primirea de catre terminal a unui Tick nou. In cazul in care un Tick nou a fost primit in timpul executarii OnTick(), acest Tick va fi ignorat – astfel OnTick() nu va fi apelat pentru executie in acest caz. Toate cotatiile primite in timpul executiei OnTick() vor fi ignorate. Functia OnTick() poate fi apelata pentru executie numai de catre terminalul client, cu conditia ca sesiunea anterioara de operare a fost finalizata si controlul a fost returnat terminalului client.

Cea mai mare parte a codului unui program trebuie sa fie inclus in cadrul functiei OnTick(). Toti operatorii, functiile integrate si cele personalizate, precum si toate prelucrarile necesare trebuie sa fie efectuate in interiorul acestei functii.

Posibilitatea de a apela și executa OnTick() este influențată de starea butonului "Enable / Disable EA" in cadrul terminalului. Dacă acest buton este în stare de “Disable EA”, terminalul client nu va face apel pentru executare, indiferent dacă au venit noi cotatii sau nu. Cu toate acestea, schimbarea stării butonul de la activat la dezactivat nu termină sesiunea curentă de funcționare a functiei.

Terminalul client nu poate apela OnTick() in cazul in care fereastra de proprietati EA este deschisa. Aceasta fereastra poate fi accesata doar atunci cand OnTick() este in asteptare pentru un nou Tick.

Incetarea unei sesiuni curente a functiei OnTick() are loc in urmatoarele cazuri:

cand programul este scos de pe un chart (diagrama pereche valutara)

in cazul in care valuta sau perioada chart-ului sunt modificate

cand un cont este schimbat sau un chart este inchis

ca rezultat al terminarii functionarii terminalului client.

Functia speciala OnDeinit()

Proprietatea distincta a functiei OnDeinit() este executarea acesteia la terminarea programului (deinitializarea). Daca un program contine o descriere a OnDeinit(), aceasta va fi apelata si executata la oprirea programului. In caz contrar, nu va fi efectuata nici o actiune la terminarea programului.

Terminalul client apeleaza functia OnDeinit() in urmatoarele cazuri:

cand este inchisa fereastra unei perechi valutare

inainte de a schimba perechea valutara sau modificarea unei perioade a unui chart

la o recompilare reusita a programului in MetaEditor

cand se modifica parametrii de intrare

Timpul de executare pentru OnDeinit() este limitat la 2.5 secunde. Daca codul functiei speciale este executat o perioada mai lunga de timp, terminalul client va termina fortat executia functiei OnDeinit().

2.2.3. Structura unui program

Head-ul este format din primele randul la inceputul unui program, care contin informatii generale despre program. Declararea si initializarea variabilelor globale se face in cadrul Head-ului.

Dupa Head-ul programului sunt descrise functiile speciale OnInit(), OnTick() si OnDeinit(). Ca regula, un program normal contine toate cele trei functii speciale OnInit(), OnTick() si OnDeinit(), care apeleaza functiile definite de utilizator. Acestea pot apela la randul lor alte functii definite de utilizator, fiecare dintr ele fiind marginita la un scop functional.

Un EA poate contine functii definite de utilizator cu cele mai diverse proprietati. Unele functii sunt destinate pentru urmarirea evenimentelor si comenzilor in curs, alte functii sunt folosite pentru a forma ordine de tranzactionare, al treilea tip de functii sunt destinate pentru efectuarea a diferite tipuri de calcule, ca de exemplu pentru definirea criteriilor de tranzactionare etc.

Decizia privind ce tipuri de functii se vor utiliza intr-un program depinde de obiectivul unui EA si de ce fel de serviciu este intentionat sa se ofere utilizatorului.

Pentru un EA de tranzactionare automatizata se pot identifica 2 module obligatorii pentru functionarea programului: modulul de procesare si modulul de plasare ordine de tranzactionare. In cadrul programului pot aparea si alte functii in legatura cu necesitatile unui EA.

Modulul de procesare este format din doua componente:

componenta de procesare a datelor de intrare

componenta de verificare a criteriilor de tranzactionare: odata ce este implinit un criteriu, controlul este cedat modului de plasare ordine de tranzactionare.

Modulul de plasare a ordinelor de tranzactionare contine de obicei o functie de definire a volumului pentru un ordin si functia de plasare a ordinelor conform cu criteriul activ. Ordinelor de vanzare/cumparare generate astfel reprezinta datele de iesire ale programului. Acestea sunt trimise spre executare catre terminalul-server.

Figura 2.2 reprezinta o diagrama a componentelor unui program cu evidentierea relatiilor dintre acestea si a fluxului informational.

Functia de prelucrare a datelor de intrare

Este cea care acceseaza datele de intrare sub forma de cotatii, volum, timp etc. din partea terminalului client si prelucreaza aceste informatii intr-o maniera relevanta pentru verificarea criteriilor de tranzactionare. Aici se pot apela indicatori integrati in platforma sau definiti de utilizator sau se pot defini functii de procesare in cadrul programului.

Functia criterii de tranzactionare

Succesul oricărei strategii de tranzacționare depinde în principal de definirea criteriilor de tranzacționare. Funcția care definește criteriile de tranzacționare este cea mai importantă parte a unui program. Criteriile de tranzactionare sunt verificate prin apelarea functiilor de prelucrare a datelor de intrare. Conform strategiei de tranzacționare, funcția poate returna valori care corespund cu anumite criterii de tranzacționare.

Figura 2.2

Într-un caz general, pot fi definite următoarele criterii:

criteriu pentru deschiderea unui ordin de piață;

criteriu de închidere a unui ordin de piață;

criteriu pentru închiderea partiala a unui ordin de piață;

criteriu de închidere a ordinelor de piață opuse;

criteriu de modificare a prețurilor solicitate de STOP-urile unui ordin de piata;

criteriu pentru plasarea de unui ordin in asteptare;

criteriu pentru eliminarea unui ordin în așteptare;

criteriu de modificare a prețului de deschidere pentru un ordin in asteptare;

criteriu de modificare a prețurile STOP-urilor pentru un ordin in asteptare.

În cele mai multe cazuri, declanșarea unui criteriu de tranzactionare nu poate avea loc concomitent cu un alt criteriu. De exemplu, dacă criteriul pentru deschiderea unui Ordin Cumpara devine relevant la un moment dat, înseamnă că criteriile utilizate pentru închiderea ordinelor Cumpara sau de plasare ordine de Vinzare nu pot fi acceptabile. În același timp, în conformitate cu normele inerente dintr-o strategie de tranzacționare data, unele criterii se pot declanșa simultan.

Functia de definire a volumului

Un trader trebuie să fie capabil să regleze numarul de loturi pentru comenzile care urmeaza sa fie plasate. Este destul de dificila crearea unei funcții universale pentru acest scop, deoarece fiecare strategie de tranzacționare presupune gestionarea volumui intr-un mod special. De exemplu, unele strategii implică posibilitatea de a lucra cu un singur ordin de piață, în timp ce altele permit deschiderea de noi comenzi pe piață, indiferent de cele existente.

Functia plasare comenzi

Aceasta functie preia criteriile activate ca rezultat al functiei criterii de tranzactionare si formeaza cererile de plasare ordine conform cu acestea.

CAPITOLUL III: Proiectarea de detaliu a aplicatiei

3.1 Definirea obiectivelor aplicatiei informatice

Tema prezentei lucrari de licenta o reprezinta realizarea unei aplicatii de tip Expert Advisor (robot de tranzactionare) pentru a fi folosita in cadrul platformei de tranzactonare online Metatrader 4.

Obiectivul aplicatiei este punerea la dispozitia utilizatorului a unui program care sa automatizeze complet procesul de tranzactionare si care sa respecte criteriile de performanta avand:

-Rezultate pozitive obtinute din simulari extensive pe perioade istorice trecute si rezultate pozitive in tranzactionarea Live.

-posibilitatea de a configura toti parametrii strategiei de tranzactionare implementate, fara ca sa fie nevoie de modificari in cod din partea utilizatorului, parametri precum: marimea unui lot de tranzactionare, nivelul leverage-ului, parametri pentru optimizarea indicatorilor, parametri pentru optimizarea criteriilor de tranzactionare.

-Existenta unui modul configurabil care sa faca managementul fondurilor utilizatorului, fixandu-se restrictii in functie de evolutia balantei contului.

3.2 Strategia de tranzactionare folosita

Aplicatia va folosi o strategie de tip mean-reversion – la baza acestui tip de strategie sta premisa conform careia pretul unei perechi valutare are tot timpul tendinta de a se intoarce catre un nivel mediu. Cand pretul se departeaza semnificativ de acest nivel, de regula se produce o corectie a acestuia in directia mediei. Pentru recunoasterea situatiilor de supra-apreciere si sub-apreciere a valutei urmata de schimbarea directiei evolutiei pretului se va folosi “Stochastic Oscilator” un indicator de tip oscilator folosit in analiza tehnica.

Prezenta aplicatie este bazata pe un indicator care analizeaza evolutia trecuta a pietei pentru a determina nivele de suport si rezistenta. Acest indicator reprezinta un element de noutate cu un algoritm complex de deducere a nivelelor care va fi descris in continuare in aceasta lucrare. Rolul indicatorului este acela de a fi un criteriu eficient de filtrare a indicatorului “Stochastic”: semnalele generate de oscilator vor fi acceptate numai daca se vor produce in imediata apropiere a unui nivel de suport sau rezistenta. Se va proceda in acest fel deoarece se observa o probabilitate statistica ridicata ca piata sa recunoasca si sa reactioneze la nivelele care au reprezentant puncte semnificative de modificare a fortelor vanzatorilor si cumparatorilor de pe piata.

In cazul in care toate criteriile de tranzactionare definite se confirma, se va plasa o comanda de intrare pe piata, de vanzare sau cumparare in functie de tipul criteriilor confirmate. Nivelele de StopLoss si TakeProfit vor fi generate tot prin intermediul indicatorului nivelelor de suport si rezistenta si atasate fiecarei comenzi din momentul executarii acesteia. In acest fel o comanda trimisa de catre aplicatie se va putea termina in conditii conforme cu strategia de tranzactionare chiar si atunci cand aplicatia nu este online.

Programul principal se va numi Licenta.mq4, la inceputul programului fiind incarcate toate extensiile, corespunzatoare cu diferite module functionale

3.3. Diagrama flux a datelor/ structura aplicatiei

3.3.1 Date de intrare

In cazul unei aplicatii de tranzactionare automatizata datele de intrare sunt reprezentate de:

– informatii in timp real legate de cotatiile de pret pentru perechi valutare. Fiecare Tick primit in timp real poate duce la confirmarea unor criterii de tranzactionare si plasarea unor comenzi noi. De asemenea sunt disponibile informatii despre evolutia recenta a graficelor si evloutia pe termen lung sub forme de arhive salvate in terminal.

– conditiile de tranzactionare impuse de server cum ar fi: volumul minim de tranzactionare, distanta minima la care pot fi plasate SL si TP de pretul de intrare, numarul de comenzi deschise simultan.

– optiunile configurate de utilizator in cadrul terminalului.

– parametri specifici de functionare a aplicatiei de tranzactionare automatizata care pot fi configurati din meniul aplicatiei.

3.3.2 Prelucrarea datelor

Aplicatia analizeaza fluxul cotatiilor de pret in timp real si executa comenzi in conformitate cu conditiile de tranzactionare impuse de server, optiunile utilizatorului si parametrii specifici ai aplicatiei.

Ca date de intrare, parametrii aplicatiei au o importanta mare deoarece pentru a asigura viabilitatea programului de tranzactionare este necesara adaptarea continua a acestuia la conditiile schimbatoare a pietei. De aceea orice aplicatie de tranzactionare necesita o parametrizare initiala pentru a asigura buna functionare a acesteia.

3.3.3 Date de iesire

In urma prelucrarilor efectuate de program vom avea ca date de iesire ordinele de comanda trimise catre server. Acestea vor contine:

– Pretul acceptat de aplicatie ca pret de intrare pe piata

-Tipul comenzii (OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_SELLSTOP, OP_BUYSTOP)

– Slippage – determina ce diferenta fata de pretul de intrare poate fi acceptata

– Volumul comenzii exprimat in loturi, unde un lot este echivalent cu 100.000 unitati din valuta cotata

– Pentru comenzile de tip “pending” se introduce si timpul de expirare a comenzii

Comanda trimisa catre server reprezinta finalitatea si obiectivul aplicatiei. Intr-o aplicatie bine optimizata orice comanda are o probabilitate pozitiva de a genera profit pe termen lung.

3.3.4 Structura apliatiei dupa cum reiese din Diagrama de flux

Din Diagrama de Flux de Date se pot urmari principalele fluxuri si prelucrari ce au loc asupra datelor. Conform diagramei (Figura 3.1), avem mai multe nivele de prelucrari:

Nivel 1

La acest nivel se calculeaza valorile indicatorilor folositi de aplicatie. Programul are acces la baza de date de cotatii a terminalului si pornind de la aceasta calculeaza valorile indicatorilor pentru fiecare Tick nou primit. Aceste valori sunt apoi preluate de catre modulul de verificare a criteriilor de plasare comenzi.

Nivel 2

La acest nivel se verifica criteriile de plasare comenzi pornind de la valorile indicatorilor calculate anterior si parametrii completati de utilizator ca date de intrare. Procesul se ramifica in functie daca sunt sau nu comenzi deschise. In aplicatia de fata nu putem avea comenzi de BUY si SELL deschise in acelasi timp. Daca criteriile de plasare a comenzilor se verifica, se trece la nivelul urmator.

Nivel 3

La acest nivel se determina toate caracteristicile comenzii ce urmeaza a fi trimisa. Se foloseste un algoritm specific pentru calculul Volumului, StopLoss si TakeProfit. Acestea se paseaza ca argumente functie propriu-zise de trimitere comanda catre server.

Nivel 4

La acest nivel se trimite cererea de plasare a comenzii catre terminal. Se verifica daca nu au aparut erori la acest nivel, iar in caz ca trimiterea comenzii a esuat se incearca retrimiterea comenzii.

Figura 3.1

3.4 Nivel 1: Calcul valori indicatori

3.4.1 Indicatorul nivelelor de suport si rezistenta

3.4.1.1 Prezentare generala a indicatorului

Indicatorul de suport si rezistenta foloseste un algoritm special de calcul al nivelelor de suport si rezistenta. Toate functiile indicatorului se salveaza in fisierul Support&Resistance.mqh,

Acesta fiind incarcat la inceputul programului principal Licenta.mq4:

#include <Support&Resistance.mqh>

3.4.1.2 Algoritmul indicatorului

Pas 1. Formarea unei liste avand ca elemente Fractalii de pe o perioada determinata

In analiza tehnica, un fractal reprezinta o extrema a mai multor lumanari, deobicei se zice ca avem un fractal atunci cand :

– exista o lumanare al carei maxim este mai mare decat maximile a cate 2 lumanari inainte si dupa aceasta.

– exista o lumanare al carei minim este mai mic decat minimele a cate 2 lumanari inainte si dupa.

Se formeaza o lista cu toti fractalii pe perioada specificata de utilizator. In acest sens se cicleaza in spate un anumit numar de lumanari ( numarul lumanarilor determinat de variabila externa BarsNo) si se verifica existenta fractalilor UP sau DOWN.

Fiecarui fractal nou gasit i se atribuie o greutate (pondere) in functie de intervalul de timp in care a aparut. Nivelul fractalului, greutatea si timpul se salveaza intr-o instanta a clasei Fractal. Din aceste instante se formeaza o lista liniara simplu inlantuita. Aceasta lista este preluata la urmatorul pas ca baza de prelucrare.

Pas 2. Se creaza un array arraySR[] cu “greutatea” fiecarei unitati de pret din intervalul de interes

La aceasta etapa se foloseste un algoritm care ia in calcul distributia fractalilor pentru a scoate in evidenta punctele de maxima intensitate sau “greutate”. In aceste zone piata a schimbat directia de mai multe ori, ceea ce inseamna ca un nivel de suport/ rezistenta a fost confirmat.

Pas 3. Se deduc nivelele finale de suport si rezistenta in array-ul niveleSR[]

Pentru a gasi nivelele de suport si rezistenta se verifica array-ul rezultat la pasul anterior (arraySR[]) pentru existenta fractalilor. Pentru calcul fractali se foloseste variabila externa FractNo. Fractalii astfel rezultati se salveaza in array-ul global niveleSR[].

niveleSR[] reprezinta rezultatul prelucrarilor indictorului de suport si rezistenta, el fiind accesat in continuare pentru testarea criteriilor de tranzactionare.

3.4.1.3 Criterii de eficienta/ structuri de date

Orice aplicatie automatizata de tranzactionare are de-a face cu cotatii in timp real, avand de-a face cu multiple Tick-uri pe secunda, Tick-ul fiind evenimentul care declanseaza corpul principal al programului. De aceea aplicatiile de acest tip trebuie proiectate avand in vedere eficienta maxima de folosire a memoriei si a puterii procesorului.

Prin urmare, pentru a optimiza consumul de memorie a proceselor indicatorului de suport si rezistenta au fost folosite cele mai eficiente structuri de stocare a datelor.

In cadrul indicatorului se folosesc urmatoarele structuri de stocare ale datelor:

Un array local arraySR[] pentru stadiul intermediar cu toate greutatile pe intervalul de referinta si un array global niveleSR[] pentru lista finala de nivele de suport si rezistenta. Aceste array-uri sunt definite dinamic si redimenstionate dinamic. S-a folosit o astfel de solutie deoarece necesarul de memorie difera de la program la program, in functie de variabila globala BarsNo, necesarul de elemente ce vor fi stocate variind de la sub 10 la peste 500.

Lista liniara simplu inlantuita ordonata pentru stocarea fractalilor pe perioada de referinta

In ultimul caz a existat nevoia unei structuri de date care sa permita sa aiba ca elemente Fractalii de pe o perioada determinata, impreuna cu detaliile weight si time. Astfel s-a impus ca solutie folosirea unei liste liniare simplu inlantuite ordonate.

Lista simplu inlantuita este formata din instante ale clasei Fractal, clasa avand urmatoarea structura:

class Fractal {

public:

double value; // valoarea – nivel de pret a fractalului

int weight; // greutatea – intensitatea fractalului

int time; // timpul in care a aparut fractalul

Fractal* next;

};

Pentru operatii pe lista se implementeaza urmatoarele functii:

void InserareInterior(Fractal* &cap, double fvalue, int fweight, int ftime) – functie ce are ca argumente Fractalul cap, valoarea, greutatea si timpul acestuia. Aceasta functie insereaza elemente noi in lista simplu inlantuita, fiind o lista ordonata pentru fiecare nou element se cauta pozitia corecta in cadrul listei.

void Stergere(Fractal* cap) – Sterge lista

3.4.1.4 Proiectarea principalelor functii

Functiile care sunt accesate din corpul programului sunt: InitializareSR[] , UpdateSR[]. Alte functii importante: CreareListaFractali[],CalculSR[].

Functia InitializareSR[]

Aceasta functie este apelata din functia speciala OnInit(), este responsabila cu calculul nivelelor de suport si rezistenta in momentul rularii programului. Functia InitializareSR[] are urmatoarea structura:

void InitializareSR() {

CreareListaFractali(prim);

CalculSR();

ultimulFractal= UltimulFractal();

}

Functia UpdateSR[]

Functia UpdateSR[] se apeleaza din cadrul functiei speciale OnTick[] in cazul in care se semnaleaza formarea unui fractal nou. Acest eveniment impune recalcularea indicatorului. Aceasta functie este la fel cu functia InitalizareSR[], doar ca aceasta contine si functia de stergere a listei liniare simplu inlantuite existente.

void UpdateSR() {

if(ultimulFractal != UltimulFractal()) { // conditie de verificare formare fractal nou

Fractal* help = prim;

Stergere(help); // stergere lista existenta

prim = NULL;

CreareListaFractali(prim);

CalculSR();

ultimulFractal= UltimulFractal();

}

}

Functia CreareListaFractali[]

Functie apelata din cadrul functiilor InitializareSR[] , UpdateSR[]. Se foloseste de functia iFractals[] pentru gasirea fractalilor.

Se prezinta mai jos o sectiune de interes din cadrul functiei. Aceasta sectiune face parte dintr-un ciclu care trece prin toate lumanarile pe o durata de timp determinata de variabila externa BarsNo.

fractVal = NormalizeDouble(iFractals(NULL,timeFrame, MODE_UPPER,i),4); //verificam daca avem fractal UP

if (fractVal > 0) //Daca a fost gasit fractal

{

fractTime = iTime(NULL,timeFrames[tf],i);

InserareInterior(cap,fractVal,fractWeight,fractTime);

}

Aceasta sectiune face parte dintr-un ciclu care trece prin toate lumanarile pe o durata de timp determinata de variabila externa BarsNo. Functia iFractals[] returneaza valoarea 0 daca lumanarea verificata nu este fractal si valoarea maxima a lumanarii in cazul in care lumanarea este un fractal. Daca a fost gasit un nou fractal acesta se insereaza in interiorul listei ordonate simplu inlantuite.

Acest extras de cod prezinta o portiune care cauta fractali noi de tip UPPER, cautarea fractalilor de tip LOWER se face intr-un mod similar.

Functia CalculSR[]

Functie apelata din cadrul functiilor InitializareSR[] , UpdateSR[]. Este o functie mai ampla care este formata din mai multe etape:

– Initializare vector intermediar arraySR[] la dimensiunea necesara. Aceasta dimensiune este data de diferenta de Points ( unitate 0.0001 a pretului ) dintre pretul minim si pretul maxim al fractalilor din lista creata in CreareListaFractali[].

Elementul arraySR[0] are rolul de a pastra un index pentru celelalte elemente. Celelalte elemente reprezinta punctele pentru care urmeaza sa fie calculata “greutatea” – ca functie a intensitatilor si dispersiei fractalilor din apropiere.

– Populare vector arraySR[] cu “greutati”, se prezinta un extras de cod din aceasta parte a functiei:

while ( p != NULL && p.value <=limitaSUP) {

if (p.value>=limitaINF) {

suma+=p.value*p.weight;

sumaGR+=p.weight;

count++;

}

p=p.next;

}

if ( count>0) {

mediaARP=suma/sumaGR;

element = NormalizeDouble(mediaARP*10000,0)-arraySR[0];

arraySR[element]=(double)sumaGR;

}

Aceasta sectiune de cod face parte dintr-un ciclu care trece prin toate intervalele definite de variabila externa Interval. Limitele intervalului sunt atribuite variabilelor limitaSUP, limitaINF.

Se cicleaza prin lista creata in CreareListaFractali[] si se cauta fractalii care fac parte din intervalul [limitaSUP,limitaINF]. Se face suma greutatilor (weight) tuturor fractalilor si suma produselor dintre pret fractal si greutate fractal. Acestea se folosesc pentru calculul mediei, respectiv mediei aritmetice ponderate a fractalilor.

Media aritmetica ponderata va fi punctul de maxima intensitate de pe interval, iar suma greutatilor va determina greutatea acestui punct.

In final se actualizeaza arraySR[] cu noile informatii.

– Ultimul pas este cautarea punctelor extreme semnificative din arraySR(). Practic se cauta fractali cu intensitatea data de variabila externa FractNo.

for (i=1; i<=max-arraySR[0];i++) {

if ( arraySR[i] > 0 && arraySR[i] >= 80 ){

avemFractal = true;

for(int j=1; j<=FractNo;j++)

if ( (i-j>0 && arraySR[i-j] >= arraySR[i]) || arraySR[i+j] >= arraySR[i] ) { avemFractal = false; break; }

if ( avemFractal == true ){

ArrayResize(niveleSR,nrNivele+1);

niveleSR[nrNivele] = (double)(i+arraySR[0])/10000;

nrNivele++;

}

}

}

Daca se gaseste un nivel de pret care respecta conditia impusa de FractNo, acest nivel este adaugat in array-ul dinamic niveleSR(). niveleSR() reprezinta rezultatul final al prelucrarilor realizate in cadrul indicatorului de Suport si Rezistenta.

Functiile CalculSup() si CalculInf()

CalculSup() si CalculInf() sunt functiile de acces catre informatiile stocare in arraySR(), mai precis CalculSup() returneaza valoare nivelului de suport sau rezistenta imediat superior nivelului curent al pretului, iar CalculInf() returneaza valoarea nivelului de suport sau rezistenta imediat inferior.

Aceste doua functii sunt accesate din cadrul modulelor:

de verificare criterii de tranzactionare ( ca metoda de sortare a unui semnal al indicatorului Stochastic ) si

de plasare a comenzilor, ele determinand nivelele StopLoss si TakeProfit asociate unui ordin de piata.

Pe langa returnarea nivelelor semnificative de suport si rezistenta aceste functii plaseaza in fereasta graficului un obiect grafic – o linie orizontala care marcheaza vizual nivelele S&R:

double CalculSup(){

int dimSR = ArraySize(niveleSR);

for ( int i = 0; i<dimSR ; i++ ) {

if ( Bid < niveleSR[i] ) {

double nivel = niveleSR[i];

double StartX = Time[1];

double StartY = nivel;

double EndX = Time[100];

double EndY = StartY;

string ObjName = DoubleToStr(nivel,4);

ObjectCreate(0,ObjName,OBJ_TREND,0,StartX,StartY,EndX,EndY);

ObjectSet(ObjName,OBJPROP_RAY,0);

ObjectSet(ObjName,OBJPROP_COLOR,Red);

return niveleSR[i];

}

}

return 0;

}

Dupa cum se poate observa din extrasul de cod de mai sus, functia CalculSUP() cauta in array-ul niveleSR() primul nivel care este mai mare decat pretul curent (Bid). In caz ca un astfel de nivel este gasit, acesta este afisat in fereastra graficului prin intermediul functiei ObjectCreate().

3.4.2 Indicatorul Stochastic

Indicatorul Stochastic este un indicator de tip oscilator foarte popular in analiza tehnica a graficelor. Acest indicator arata pozitia nivelului de Close ( Inchidere/Finalizare ) a unei lumanari relativ la intervalul High – Low ( Cea mai joasa si cea mai ridicata valoare a pretului ) pe o perioada data.

Acest indicator urmareste forta motrice a pretului (momentum-ul), furnizand semnale destul de exacte pentru starile de Over-Bought (Supra-apreciere a valutei) si Over-Sold (sub-apreciere a valutei).

Stochastic este format din doua linii/semnale:

– linia 1 – linia de baza – semnaleaza starea de Over-Bought atunci cand depaseste valoarea de 80 si starea de Over-Sold atunci cand coboara sub valoarea de 20.

– linia 2 – linia de semnal – este un Simple Moving Average ( Medie mobila simpla ) a liniei de baza. In momentul in care linia de semnal intersecteaza linia de baza dupa o intrare in zonele Over-Bought sau Over-Sold spunem ca avem un semnal de vanzare sau cumparare generat de indicatorul Stochastic.

Indicatorul Stochastic folosit este indicatorul standard, prin urmare codul acestui indicator nu va fi analizat in prezenta lucrare.

3.5 Nivel 2: Criterii de tranzactionare

Functiile de la Nivelul 2 logic al aplicatiei indeplinesc functia de verificare a criteriilor de tranzactionare. Acest nivel este important pentru ca la acest nivel se declanseaza pregatirea ordinelor de comanda.

Pentru verificarea criteriilor se folosesc indicatorii Suport / Rezistenta si Stochastic descrisi anterior. Functiile responsabile de criteriile de tranzactionare sunt grupate in cadrul CriteriiTranzactionare.mqh.

Functii Importante

Functiile importante de la acest nivel sunt VerificareCriteriiTranzactionare() si CalculateStochasticValue().

CalculateStochasticValue()

Functie care verifica criteriile determinate de intersectarea liniilor de semnal ale indicatorului Stochastic. Functia returneaza:

-1 in cazul in care nici un criteriu nu este verificat.

Valoarea liniei de baza continuta de variabia main1 ( intre 0 si 100 ) in cazul in care un criteriu este verificat.

int CalculateStochasticValue(){

int main0,main1,signal0,signal1;

main0 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_MAIN,1);

signal0 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_SIGNAL,1);

main1 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_MAIN,2);

signal1 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_SIGNAL,2);

if ( main1 > signal1 && main0 < signal0 && main1 > 80) return main1;

if ( main1 < signal1 && main0 > signal0 && main1 < 20) return main1;

return(-1);

}

VerificareCriteriiTranzactionare()

Aceasta functie returneaza o valoare de tip int, dupa cum urmeaza:

-1 in cazul in care nu s-a confirmat nici-un criteriu

0 (OP_BUY) in cazul in care a fost verificat criteriul de plasare de comenzi de cumparare

1 (OP_SELL) in cazul in care a fost verificat criteriul de plasare de comenzi de vanzare

int VerificareCriteriiTranzactionare(){

double sup,inf;

int valStochastic;

valStochastic = CalculateStochasticValue();

if ( CheckOrders() == false && valStochastic != -1 ){

ObjectsDeleteAll(0,OBJ_TREND);

sup = CalculSUP();

inf = CalculINF();

CreateVline();

double up,down,up2,down2;

up = sup+5*Point*10;

down = sup-10*Point*10;

up2 = inf+10*Point*10;

down2 = inf-5*Point*10;

if ( sup != 0 && inf != 0 && (sup-inf)*10000>40){

if ( valStochastic >= 80 && ( Bid>=down && Bid<up )) return(OP_SELL);

if ( valStochastic <= 20 && ( Bid>=down2 && Bid<up2 )) return(OP_BUY);

}

}

return(-1);

}

Functia incepe prin a calcula valoarea indicatorului Stochastic prin CalculateStochasticValue(), in cazul in care valoarea acestuia este diferita de -1 si valoarea functiei CheckOrders() este false se trece la verificarea criteriului de proximitate a unui nivel se suport sau rezistenta. ( Functia CheckOrders() verifica daca exista comenzi deschise – strategia de tranzactionare nu permite existenta a mai multe comenzi deschise in acelasi timp)

Pentru verificarea criteriului de proximitate se calculeaza nivelele de suport si rezistenta imediat superioare prin intermediul functiilor CalculSUP() si CalculINF(). Urmatorul pas este calcularea intervalelor de toleranta:

Interval pentru criteriu SELL: [down,up] – determinat de nivelul superior de suport sau rezistenta +/- 5, 10 Points

Interval pentru criteriu BUY: [down2,up2] – determinat de nivelul inferior de suport sau rezistenta +/- 5, 10 Points

In final, daca exista nivele superiorare si inferiorare de S&R, iar diferenta dintre ele este mai mare decat un numar de de points, se vor verifica conditiile de tranzactionare:

Conditie SELL: if ( valStochastic >= 80 && ( Bid>=down && Bid<up )) return(OP_SELL);

Conditie BUY: if ( valStochastic <= 20 && ( Bid>=down2 && Bid<up2 )) return(OP_BUY);

3.6 Nivel 3: Calcul atribute comanda

Pe acest nivel se intra in cazul in care a fost verificat un criteriu de tranzactionare. Functiile responsabile pentru calcul atribute comanda sunt grupate logic in cadrul PlasareComenzi.mqh.

In cadrul functiei OnTick() se atribuie variabilei de tip int CRITERIU valoarea rezultata a functiei VerificareCriteriiTranzactionare(). In cazul in care CRITERIU ia valoarea OP_BUY (1) sau OP_SELL (0) se declanseaza procedura de plasare comenzi prin intermediul functiilor BuySignal() si SellSignal().

int CRITERIU = VerificareCriteriiTranzactionare();

switch (CRITERIU) {

case OP_BUY: BuySignal(); break;

case OP_SELL: SellSignal(); break;

}

Functiile BuySignal() si SellSignal() au structura dupa cum urmeaza:

void BuySignal(){

double volume, SL, TP;

SL = CalculINF()-100*Point;

TP = CalculSUP();

volume = CalculVolum(SL,TP);

SendBuyOrder(volume,SL,TP);

}

void SellSignal(){

double volume, SL, TP;

SL = CalculSUP()+100*Point;

TP = CalculINF();

volume = CalculVolum(SL,TP);

SendSellOrder(volume,SL,TP);

}

Calcul SL (StopLoss)

Stop Loss este o conditie de siguranta care limiteaza pierderea maxima pe care o poate inregistra o tranzactie. Nivelul Stop Loss este acel nivel de pret, sub pretul de intrare pe piata in cazul unei comenzi de cumparare si peste nivelul de intrare in cazul unei comenzi de vanzare, la care comanda activa va fi inchisa in pierdere.

Stop Loss va fi calculat in functie de nivelul de suport sau rezistenta superior in cazul unei comenzi de vanzare si in functie de nivelul inferior in cazul unei comenzi de cumparare.

Calcul TP (TakeProfit)

Take Profit determina target-ul de profit al unei tranzactii. Nivelul Take Profit este acel nivel de pret, peste pretul de intrare pe piata in cazul unei comenzi de cumparare si sub nivelul de intrare in cazul unei comenzi de vanzare, la care comanda activa va fi inchisa in profit.

Take Profit va fi calculat in functie de nivelul de suport sau rezistenta inferior in cazul unei comenzi de vanzare si in functie de nivelul superior in cazul unei comenzi de cumparare.

Nivelele StopLoss si TakeProfit sunt atasate fiecarei comenzi trimise catre server, in asa fel incat este garantata executarea acestora chiar si atunci cand programul de tranzactionare este offline.

Calcul Volum

Volumul este un atribut important al unei comenzi, acesta defineste valoarea tranzactiei, precum si potentialul de profit/pierdere. Calculul volumului are un rol important in managementul riscului in tranzactionarea cu valute si alte instrumente financiare.

In cazul prezentei aplicatii, volumul va fi determinat in functie de nivelele SL(StopLoss) , Tp(TakeProfit) si variabila externa VolumePercentage.

Functia CalculVolum() este apelata din cadrul functiilor BuySignal()/SellSignal() ,primeste ca argumente nivelele SL si TP si returneaza o valoare de tip double care reprezinta volumul tranzactiei exprimat in numarul de loturi din valuta contului de trader.

1 Lot este echivalentul a 100.000 de unitati monetare dintr-o anumita valuta, iar volumul minim permis de tranzactionare la majoritatea brokerilor Forex este de 0.01 Loturi.

double CalculVolum(double SL, double TP){

double raport,procent,pipValue,volum,equity;

raport = NormalizeDouble(MathAbs(TP-Bid)/MathAbs(SL-Bid),2);

procent = NormalizeDouble(VolumePercentage/raport/100,3); //procent din equity

pipValue = (AccountEquity() * procent) / NormalizeDouble(MathAbs(SL-Bid)*10000,0) ;

volum = NormalizeDouble(pipValue/10,2);

return(volum);

}

In vederea calculului volumui se calculeaza la inceput raportul dintre:

Numarul de Point-uri dintre pretul actual si nivelul Take Profit

Numarul de Point-uri dintre pretul actual si nivelul Stop Loss

Acest raport reprezinta un indicator de Risk/Reward ( risc raportat la beneficiu potential ). Acest indicator va lua valori >=1 daca valoarea potentiala a castigului este mai mare sau egala decat valoarea potentiala a pierderii si valori si valori in intervalul (0,1) daca valoarea potentiala a castigului este mai mica decat valoarea potentiala a pierderii.

Urmatorul pas il reprezinta calculul procentului echitatii pornind de la valoarea variabilei externe VolumePercentage. Variabila VolumePercentage reprezinta procent-ul din echitate pe care utilizatorul este dispus sa il riste cu o tranzactie care are un raport Risk/Reward de 1. De aceea, pentru a calcula procentul final se ajusteaza valoarea VolumePercentage cu ajutorul valorii raport obtinute la pasul precedent.

In continuare se calculeaza valoarea unui Pip ca raport intre valoarea de unitati monetare care se risca sa se piarda si numarul de Point-uri dintre pretul actual si nivelul Stop Loss. Valoarea finala a volumului va reiesi din variabila pipValue, se foloseste functia NormalizeDouble() pentru a rotunji volumul la doua zecimale.

SendBuyOrder() si SendSellOrder()

Dupa ce Volumul si nivelele StopLoss si TakeProfit au fost calculate, acestea se paseaza ca argumente la functiile SendBuyOrder(), respectiv SendSellOrder(), functii responsabile cu trimiterea comenzilor catre terminal.

3.7 Nivel 4: Trimiterea comenzilor catre terminal

La acest nivel se gasesc functiile de plasare a comenzilor SendBuyOrder() si SendSellOrder() si functia Errors() de verificare a erorilor. Aceste functii trimit comenzi catre terminal prin functia standard OrderSend(), folosind ca argumente valorile atributelor calculate la nivelul precedent.

Functiile SendBuyOrder() si SendSellOrder()

Aceste functii trimit comenzi catre terminal prin functia standart OrderSend(), folosind ca argumente valorile atributelor calculate la nivelul precedent.

Functia OrderSend() returneaza numarul ticket-ului atribuit comenzii de catre server sau -1 in cazul in care plasarea comenzii a esuat. Pentru a culege mai multe informatii despre erori se foloseste functia standart GetLastError().

int  OrderSend(
   string   symbol,              // Simbol/perechea valutara care se tranzactioneaza
   int      cmd,                 // tipul operatiei
   double   volume,              // volum
   double   price,               // nivelul de pret la care se executa comanda
   int      slippage,            // deviata permisa de la pret
   double   stoploss,            // stop loss
   double   takeprofit,          // take profit
   string   comment=NULL,        // commentariu
   int      magic=0,             // magic number
   datetime expiration=0,        // timp expirare comanda in asteptare
   color    arrow_color=clrNONE  // culoare
   );

In cadrul functiilor SendBuyOrder() si SendSellOrder() avem un ciclu while in interiorul caruia avem apelul functiei OrderSend(). Se iese din ciclu in urmatoarele cazuri:

Comanda a fost plasata, ceea ce implica o valoare mai mare ca 0 a valorii returnate de functia OrderSend(), valoare salvata in variabila in Ticket

Comanda nu a fost plasata si a fost intampinata o eroare critica, ceea ce implica o valoare mai mica decat 1 a valorii returnate de functia OrderSend(), valoare salvata in variabila in Ticket

Se prezinta mai jos codul functiei SendBuyOrder(), cel al functiei SendSellOrder() este analog.

void SendBuyOrder(double volume, double SL, double TP){

int Ticket;

while(true){

Ticket = OrderSend(NULL,OP_BUY,volume,Ask,3,SL,TP,NULL,12345,0,Blue);

if (Ticket>=0) return;

else { // avem eroare

if(Errors(GetLastError())==false)// Daca eroarea e critica

return;

}

}

}

Functia Errors()

Aceasta functie este apelata in cazul in care Ticket-ul returnat de functia OrderSend() este mai mic decat 1, ceea ce se interpreteaza ca o incercare esuata de plasare a comenzii. In acest caz este necesara verificarea motivului pentru care plasarea comenzii a esuat, se verifica codul erorii aparute in momentul incercarii de plasare a comenzii.

In functie de gravitatea erorii se disting urmatoarele cazuri:

Erori Non-Critice: Sunt erori care pot fi remediate si se va incerca retrimiterea comenzii catre server. Functia Errors() va returna valoarea true. Exemple de erori Non-Critice:

Eroare cod 129: Pret Nevalid

Eroare cod 135: Pretul s-a modificat

Eroare cod 136: Nu exista cotatii

Eroare cod 146: Subsistemul de tranzactionare este ocupat

Erori Critice: Sunt erori care nu pot fi remediate, prin urmare functia Errors() va returna valoarea false, ca urmare se va iesi din ciclul while din functia SendBuyOrder()/SendSellOrder() din cadrul careia a fost apelata . Exemple de erori Critice:

Eroare cod 2: Eroare comuna

Eroare cod 5: Versiune invechita a terminalului client

Eroare cod 64: Cont Blocat

Eroare cod 133: Tranzactionare interzisa

bool Errors(int Error) {

if(Error==0)

return(false); // Nu exista eroare

switch(Error){ // Erori non- critice

case 129: // Pret Gresit

case 135: // Pretul s-a schimbat

RefreshRates(); // Se reinoieste informatia

return(true);

case 136: // Nu exista cotatii, se asteapta un nou tick

while(RefreshRates()==false) // inaintea unui nou Tick

Sleep(1); // se face un delay

return(true);

case 146: // Subsistemul de tranzactionare este ocupat

Sleep(500); // solutie simpla

RefreshRates(); // Se reinnoieste informatia

return(true);

// Erori critice:

case 2 : // Eroare comuna

case 5 : // Versiune invechita a terminalului client

case 64: // Cont blocat

case 133: // Tranzactionare interzisa

default: // Alte variante

return(false); // Eroare critica

}

}

CAP. IV PREZENTAREA APLICATIEI

4.1 Instalarea aplicatiei automatizate de tranzactionare pe piata valutara

Pentru instalarea aplicatiei automatizate de tranzactionare descrise in aceasta lucrare este nevoie de instalarea in prealabil a platformei de tranzactionare MetaTrader 4, aceasta reprezentand mediul de functionare al programului.

Se poate folosi ca baza platforma MetaTrader 4 pusa la dispozitie de orice broker acreditat.

Folderul de instalare al aplicatiei contine urmatoarele fisiere:

Licenta.mq4 si Licenta.ex4 – codul sursa si fisierul executabil

CriteriiTranzactionare.mqh, PlasareComenzi.mqh, Support&Resistance.mqh – fisiere de tip “include” care contin functii in functie de rolul acestora in program

BillWilliams.mqh si Stochastic.mq4/Stochastic.ex4 – codurile sursa si executabilele pentru indicatorii Fractals si Stochastic.

In vederea instalarii programului de tranzactionare trebuie determinat adresa folder-ului de date al prezentei instalari MetaTrader 4. Pentru aceasta se acceseaza din cadrul platformei MT4: File -> Open Data Folder si se noteaza adresa din fereastra deschisa, de forma: C:\Users\“windows user”/ AppData\Roaming\MetaQuotes\Terminal\E041987A4DFC0

Urmatorul pas il reprezinta copierea fisierelor din folder-ul de instalare in folder-ul de date al terminalului:

Licenta.mq4, Licenta.ex4 in “ …(Data Folder)/MQL4/experts”

CriteriiTranzactionare.mqh, PlasareComenzi.mqh, Support&Resistance.mqh in “ …(Data Folder)/MQL4/include”

BillWilliams.mq4 in “ …(Data Folder)/MQL4/include/indicators”

Stochastic.ex4, Stochastic.mq4 in ““ …(Data Folder)/MQL4/indicators”

Pentru a verifica daca programul a fost instalat cu succes acesta va aparea in cadrul terminalului MT4: Navigator (Panoul de navigare) -> Expert Advisors.

4.2 Rularea aplicatiei automatizate de tranzactionare pe piata valutara

Pentru a rula un program automatizat de tranzactionare trebuie activata optiunea de tranzactionare automata din setari: Tools -> Settings -> Expert Advisors -> se bifeaza “Allow automated trading” a se vedea Figura 4.2.1. Dupa aceea se apasa butonul “AutoTrading” de pe bara de unelte. In acest moment programul poate fi atasat unui grafic al unei perechi valutare.

Pentru a atasa programul unui grafic al unei perechi valutare se apasa click-dreapta pe denumirea expert-advisor-ului din cadrul ferestrei Navigator-> Expert Advisors si se selecteaza “Attach to a chart” a se vedea Figura 4.2.2. Aceasta actiune va atasat programul graficului selectat in acel moment si va afisa fereastra de configurari.

Figura 4.2.1 Activarea optiunii de tranzactionare automatizata

Figura 4.2.2 Atasarea aplicatiei de tranzactionare automatizata la un grafic

4.3 Meniul de configurare a aplicatiei

In fereastra de configurare a expert-advisor-ului vom avea un panou de configurari comune (Common – prezent in aceeasi forma in toate programele automatizate de tranzactionare pentru MT4) si panoul de configurari ale variabilelor externe definite in cadrul programului (Inputs).

Panoul “Common” permite selectarea tipului de comenzi ce pot fi plasate ( Numai Vanzare, Numai Cumparare, Ambele ), acordarea permisiei pentru tranzactionare live si alte setari de siguranta. (Figura 4.3.1)

Panoul “Inputs” permite configurarea variabilelor externe. Pentru a maximiza sansele de profitabilitate a programului, utilizatorul trebuie sa treaca printr-un proces de parametrizare si testare a aplicatiei pe diferite perechi valutare si intervale de timp pentru a determina valorile variabilelor externe. (Figura 4.3.2)

Optiunea de configurare a variabilelor externe confera programului de tranzactionare un grad ridicat de adaptabilitate si flexibilitate.

Figura 4.3.1 Sub-meniul “Common”

Figura 4.3.2 Sub-meniul “Inputs”

4.4 Optimizarea si testarea aplicatiei

4.4.1 Folosirea StrategyTester in vederea optimizarii si testarii aplicatiei

StrategyTester este o fereastra multifunctionala din cadrul terminalului MetaTrader 4 care permite testarea si parametrizarea programelor automatizate de tranzactionare inainte de utilizarea acestora pentru tranzactionare live.

Acest lucru permite evaluarea eficientei Expert-adviser-elor si confirma daca acestea functioneaza conform asteptarilor. De asemenea, permite optimizarea parametrilor programului pentru a gasi combinatia de variabile care va produce rezultatele cele mai favorabile.

Pentru a deschide fereastra “Tester”, se acceseaza in cadrul meniului principal: View > Strategy Tester. Aceasta actiune va deschide fereastra “Tester” in josul ferestrei MT4. (Figura 4.4.1)

La inceput, sunt vizibile numai tab-urile Setting si Journal, iar pe masura ce sunt facute anumite actiuni, o sa apara si alte tab-uri:

Settings – setarile testarii si optimizarii, de exemplu se poate selecta perioada de timp pentru testare.

Results – rezultatele comenzilor efectuate pe date istorice de catre program.

Graph – o afisare grafica a rezultatelor

Report – un raport detaliat al testarii efectuate

Journal – aici sunt inregistrate toate actiunile si notificarile interne ale programului

Optimization Results –informatii legate de orice pas de optimizare

Optimization Graph – rezultatele optimizarii sub forma grafica

Pentru a incarca un Expert Advisor, se da click pe tab-ul Settings in fereastra Tester. De aici, utilizatorul poate selecta:

Expert Advisor – programul automatizat de tranzactionare care va fi testat – numai programele compilate vor aparea aici

Expert Properties – Din momentul in care un Expert a fost selectat, de aici se pot selecta parametrii pentru urmatoarele categorii: Testing ( testare ), Inputs ( date intrare ) si Optimization (optimizare). (Figura 4.4.2)

Symbol and Period – Perechea valutara pe care se va efectua testarea se defineste din campul Symbol. Intervalul de timp este specificat in campul Period.

Use Date – Intervalul de timp istoric pe care se va efectua testarea

Optimization – Se bifeaza pentru activarea modului de optimizare

Figura 4.4.1 Meniul StrategyTester

Figura 4.4.2 StrategyTester > Expert Properties ( proprietati expert)

4.4.2 Parametrizarea aplicatiei

Parametrizarea unui program de tranzactionare automatizat se refera la optimizarea variabilelor externe ale acestuia pentru a maximiza sansele de a avea un rezultat pozitiv in tranzactionarea la un moment dat in timp, pe o anumita pereche valutara.

Parametrizarea este un pas obligatoriu de facut inainte de tranzactionarea live pentru orice utilizator, indiferent daca este incepator sau avansat. Motivul este acela ca pietele financiare, iar in cazul de fata pietele valutare, sunt in permanenta schimbare de dinamica.

Astfel, perioade de trending ( miscare directionala sustinuta ) alterneaza cu perioadele de ranging ( miscare orizontala, pretul fiind “inchis” pentru o perioada mai lunga de timp intr-un anumit interval). In acelasi timp, starile de trending si ranging au diferite particularitati. Din acest motiv, este necesara determinarea starii curente a pietei si a unei previziuni a evolutiei acesteia in viitorul apropiat pentru a putea alege strategia de tranzactionare cea mai potrivita.

Odata ce a fost aleasa strategia de tranzactionare, trebuie efectuata parametrizarea acesteia pentru a reflecta cat mai bine caracteristicile pietei. In acest sens, Strategy Tester din MetaTrader 4 pune la dispozitie o unealta pentru analiza evolutiei anterioare a unei perechi valutare si determinarea setului de parametri care ar fi produs rezultatele cele mai bune.

Pentru programul automat de tranzactionare prezentat in aceasta lucrare, se va efectua parametrizarea pentru perechile valutare USD/CAD ( Dolar American/Dolar Canadian ) si USD/CHF ( Dolar American/ Franc Elvetian ).

Se vor completa conditiile de optimizare pentru fiecare variabila optimizata ( Tester > Expert Properties > Inputs > Figura 4.4.3/4.4.4):

Intervalul de optimizare, determinat de valorile Start si Stop.

Pasul de optimizare, determinat de valoarea Step.

Criteriul de optimizare folosit va fi Balance ( Soldul final ).

Variabilele externe optimizare vor fi: BarsNo, Interval, FractNo. Vor fi rulate doua sesiuni de optimizare:

1. Optimizarea BarsNo

BarsNo este variabila externa care determina lungimea intervalului de timp care va fi folosit pentru determinarea nivelelor de suport si rezistenta. BarsNo va lua valori mai mici pentru pietele cu frecventa de oscilatie mare si amplitudinea redusa si valori mai mari pentru piete cu frecventa de oscilatie mica si amplitudinea mare.

Intervalul si pasul de optimizare vor fi determinate de:

Start = 5 / Step = 1 / Stop = 16

O sesiune de optimizare va genera valorile Account Balance ( Sold final ) pentru fiecare valoare a variabilei determinate de intervalul si pasul de optimizare.

Graficul si rezultatul optimizarii pentru perechea valutara USD/CAD sunt prezentate in Figura 4.1. Din ele rezulta ca valoarea optima a parametrului BarsNo este 9.

Graficul si rezultatul optimizarii pentru perechea valutara USD/CHF sunt prezentate in Anexa 4.1. Din ele rezulta ca valoarea optima a parametrului BarsNo este 10.

Figura 4.4.3 Meniul de optimizare / Inputs

Figura 4.4.4 Meniul de optimizare / Optimization

2. Optimizarea comuna variabile Interval si FractNo

Interval este variabila externa care determina latimea intervalului de pret pe care se calculeaza nivelele de suport si rezistenta si intensitatea acestora.

FractNo este variabila externa care determina distanta minima dintre doua nivele de suport si rezistenta consecutive.

Variabilele FractNo si Interval vor lua valori mai mici pentru pietele cu frecventa de oscilatie mare si amplitudinea redusa si valori mai mari pentru piete cu frecventa de oscilatie mica si amplitudinea mare.

Intervalele si pasii de optimizare vor fi:

Interval: Start = 10 / Step = 1 / Stop = 21

FractNo: Start = 5 / Step = 1 / Stop = 16

O sesiune de optimizare va genera valorile Account Balance ( Sold final ) pentru fiecare combinatie posibila de valori ale variabilelor Inteval si FractNo, determinate de intervalele si pasii de optimizare definiti.

Graficele si rezultatul optimizarii pentru perechea valutara USD/CAD sunt prezentate in Figura 4.1. Din graficul de densitate reiese zona cu cea mai mare densitate a profitului: valoarea Interval = 14 , FractNo = 15.

Graficele si rezultatul optimizarii pentru perechea valutara USD/CHF sunt prezentate in Figura 4.2. Din graficul de densitate reiese zona cu cea mai mare densitate a profitului: valoarea Interval = 15 , FractNo = 9.

Figura 4.1

Figura 4.2

4.4.3 Testarea Expert-Advisorului – rezultatele obtinute de aplicatie pe date de test

Dupa parametrizarea programului, urmatorul pas este testarea aplicatiei in Strategy Tester folosind ca date de test istoricul Tick-urilor pentru perechile valutare de interes.

Pentru inceput, se seteaza variabilele externe in Tester > Settings > Expert Properties > Inputs, dupa cum urmeaza:

USD/CAD : BarsNo = 9 Interval = 14 FractNo = 15

USD/CHF : BarsNo = 10 Interval = 15 FractNo = 9

Perioada folosita este M30 ( O lumanare este echivalentul a 30 de minute ) si intervalul de test este 2014.05.01 – 2015.05.01.

Rezultatele rularii aplicatiei pe perioada de test pentru perechea valutara USD/CHF se gasesc in Figura 4.3, rezultatele pentru perechea valutara USD/CAD se gasesc in Anexa 4.3.

Pentru interpretarea rezultatelor se folosesc urmatoarele notiuni:

Initial deposit – depozitul initial, pentru acest test se foloseste un depozit initial de 10000 USD

Total net profit – profitul total net, cel mai important criteriu de evaluare al performantelor unui program automatizat de tranzactionare. Este reprezentat de diferenta dintre profitul brut si pierderea bruta: Total net profit = Gross profit – Gross loss.

Profit factor – factorul de profit, este reprezentat de raportul dintre Gross profit si Gross loss: Profit factor = Gross profit / Gross loss. Profit factor ia valori > 1 atunci cand programul de tranzactionare este profitabil. Valori > 1.5 semnaleaza performante deosebite ale programului.

Absolute drawdown – reprezinta diferenta dintre depozitul initial si cea mai mica valoare a balantei contului inregistrata in timpul testarii.

Total trades – numarul total de tranzactii executate pe perioada testarii.

Expected payoff – se calculeaza dupa formula:

Expected payoff = (ProfitTrades / TotalTrades) * (GrossProfit / ProfitTrades) –

(LossTrades/TotalTrades) * (GrossLoss/LossTrades)

Maximal drawdown – este cea mai mare diferenta dintre un extrem local superior si urmatorul extrem inferior.

Relative drawdown – reprezinta ratia dintre Maximal drawdown si nivelul extrem local superior.

Profit trades ( % of total ) – procentul total de tranzactii profitabile ( Profit trades / Total trades)

Figure 4.3

4.4.4 Interpretarea performantei aplicatiei pe date de test

Se prezinta rezultatele obtinute din testarea programului automat de tranzactionare:

USD/CAD

Initial deposit 10000.00

Total net profit 881.26 Gross profit 1574.24 Gross loss 692.98

Profit factor 2.27

Absolute drawdown 14.64 Maximal drawdown 263.70 (2.54%) Relative drawdown 2.54% (263.70)

Total trades 21 Short positions (won %) 9 (11.11%) Long positions (won %) 12 (66.67%)

Profit trades (% of total) 9 (42.86%)

Largest profit trade 200.14 loss trade 101.59

Average profit trade 174.92 loss trade 57.75

USD/CHF

Initial deposit 10000.00

Total net profit 1555.82 Gross profit 3478.27 Gross loss 1922.44

Profit factor 1.81

Absolute drawdown 87.97 Maximal drawdown 951.01 (8.09%) Relative drawdown 8.09% (951.01)

Total trades 20 Short positions (won %) 9 (33.33%) Long positions (won %) 11 (45.45%)

Profit trades (% of total) 8 (40.00%)

Largest profit trade 482.68 loss trade 275.53

Average profit trade 434.78 loss trade 160.20

Cele doua sesiuni de testare difera prin valoarea variabilei externe VolumePercentage, responsabila pentru managementul riscului. Pentru USD/CAD s-a folosit o valoare de 2%, iar pentru USD/CHF 4%, ceea ce se reflecta intr-un profit net total mai mare pentru a doua pereche.

Pentru ambele perechi valutare, programul de tranzactionare testat a adus un venit superior celui care poate fi obtinut pe pietele financiare prin o investitie in titlurilor de valoare sigure ( Ex: Obligatiuni SUA). Pentru USD/CAD s-a inregistrat un venit anual de 8,8%, pentru USD/CHF 15,6%.

Procentul de tranzactii incheiate in profit este sub 50% in ambele cazuri, dar rezultatul se interpreteaza ca fiind unul pozitiv deoarece valoarea medie a unei tranzactii profitabile depaseste semnificativ valoarea medie a unei tranzactii in pierdere:

USD/CAD : valoarea medie a unei tranzactii profitabile 174.92 – cu 300% mai mare decat valoarea medie a unei tranzactii in pierdere ( 57.75 ).

USD/CHF : valoarea medie a unei tranzactii profitabile 434.78 – cu 270% mai mare decat valoarea medie a unei tranzactii in pierdere ( 160.2 ).

Factorul de profit ( Profit Factor ) este de 2.27 pentru USD/CAD si 1.81 pentru USD/CHF. Astfel rezulta ca performanta programului automatizat de tranzactionare este mai constanta, cu un risc mai mic pentru perechea USD/CAD.

Performanta superioara a perechii USD/CAD se reflecta si prin valoarea Maximal drawdown, de numai 2,54 %, in comparatie cu 8,09 % pentru USD/CHF.

4.5 Concluzii privind eficienta aplicatiei automatizate de tranzactionare

Asa cum reiese din datele de test obtinute pentru perechile valutare USD/CAD si USD/CHF, programul automatizat de tranzactionare proiectat in prezenta lucrare respecta criteriile de performanta pe care trebuie sa le indeplineasca un Expert advisor pentru a putea fi folosit in tranzactionare live:

– are posibilitatea de optimizare a parametrilor pentru a fi aplicat pe diferite perechi valutare si diferite tipuri de piete.

– are rezultate pozitive inregistrate pe date de test pe mai multe perechi valutare. Rezultatele financiare ale programului sunt semnificativ superioare celor care pot fi obtinute prin investitia in titluri de valoare sigure.

– curba relativ uniform ascendenta a balantei contului, cu valori mici ale Maximal drawdown, permite utilizatorilor sa foloseasca loturi mai mari de tranzactionare, maximizand astfel profitul asteptat, ramanand in limitele unui Maximal drawdown de sub 10%.

– este simplu in utilizare, putand fi folosit atat de catre utilizatorii cu experienta, cat si de utilizatorii incepatori.

Toate acestea recomanda prezentul program automatizat de tranzactionare pentru a fi utilizat de catre utilizatori in tranzactionare live, cu o probabilitate de succes, cu conditia sa fie indepliniti in prealabil pasii necesari de optimizare si testare.

ANEXE:

Anexa 3.1 Licenta.mq4

#include <Support&Resistance.mqh>

#include <CriteriiTranzactionare.mqh>

#include <PlasareComenzi.mqh>

extern int BarsNo=10;

extern int Interval = 15;

extern int FractNo=10;

extern double VolumePercentage=4;

int timeFrames[3] = {240,60,30};

//double ultimulFractal;

Fractal* prim = NULL;

// initializare lista

int OnInit()

{

InitializareSR(); //Initializeaza array-ul niveleSR[]

}

void OnDeinit(const int reason)

{

//–

Stergere(prim);

}

void OnTick()

{

static datetime Time0; if (Time0 == Time[0]) return; Time0 = Time[0];

UpdateSR(); // Se actualizeaza nivelele SR daca apare un nou fractal

int CRITERIU = VerificareCriteriiTranzactionare();

switch (CRITERIU)

{

case OP_BUY: BuySignal(); break;

case OP_SELL: SellSignal(); break;

}

}

Anexa 3.2 CriteriiTranzactionare.mqh

int VerificareCriteriiTranzactionare()

{

double sup,inf;

int valStochastic; //se salveaza nivelele S&R imediat superioare si inferioare

// Verificam daca a aparut o noua lumanare

valStochastic = CalculateStochasticValue(); //Print("STOCHASTIC :",valStochastic);

if ( CheckOrders() == false && valStochastic != -1 )

{

ObjectsDeleteAll(0,OBJ_TREND);

sup = CalculSUP(); //Print("SUPERIOR :",sup);

inf = CalculINF(); //Print("INFERIOR :",inf);

CreateVline();

double up,down,up2,down2;

up = sup+5*Point*10; //Print(up);

down = sup-10*Point*10; //Print(down);

up2 = inf+10*Point*10; //Print(up);

down2 = inf-5*Point*10; //Print(down);

if ( sup != 0 && inf != 0 && (sup-inf)*10000>40)

{

//Print(valStochastic," ",down," ",up);

if ( valStochastic >= 80 && ( Bid>=down && Bid<up )) return(OP_SELL);

//Print("SEMNAL BUY ",TimeToStr(Time[0]));

if ( valStochastic <= 20 && ( Bid>=down2 && Bid<up2 )) return(OP_BUY);

//Print("SEMNAL SELL ",TimeToStr(Time[0]));

}

}

return(-1);

}

int CalculateStochasticValue()

{

int main0,main1,signal0,signal1;

main0 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_MAIN,1);

signal0 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_SIGNAL,1);

main1 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_MAIN,2);

signal1 = iStochastic(NULL,0,8,3,3,MODE_SMA,0,MODE_SIGNAL,2);

//Print(main1," ",signal1," ",main0," ",signal0);

if ( main1 > signal1 && main0 < signal0 && main1 > 80) return main1;

if ( main1 < signal1 && main0 > signal0 && main1 < 20) return main1;

return(-1);

}

void CreateVline()

{

string ObjName = DoubleToStr(Bid,4);

//Print(ObjName);

ObjectCreate(NULL,ObjName,OBJ_VLINE,0,Time[1],Bid);

ObjectSet(ObjName,OBJPROP_COLOR,Blue);

}

bool CheckOrders()

{

if ( OrdersTotal() > 0 ) return true;

}

Anexa 3.3 Support&Resistance.mqh

class Fractal

{

// datele efective memorate

public:

double value;

int weight;

int time;

// legatura catre nodul urmator

Fractal* next;

};

double ultimulFractal;

double niveleSR[]; //Aici salvam Nivelele de Suport si Rezistenta calculate

//+––––––––––––––––––––––+

//+––––––––––––––––––––––+

void UpdateSR()

{

if(ultimulFractal != UltimulFractal())

{

Fractal* help = prim;

Stergere(help);

prim = NULL;

CreareListaFractali(prim);

CalculSR();

ultimulFractal= UltimulFractal();

}

}

void InitializareSR()

{

CreareListaFractali(prim);

CalculSR();

ultimulFractal= UltimulFractal();

}

void CreareListaFractali(Fractal* &cap)

{

double fractWeight, fractVal;

int fractTime,candle,i;

for(int tf=0;tf<3;tf++) // ciclu pentru fiecare TF in parte

{

switch(tf){

case 0:fractWeight = 80;candle=BarsNo; break;

case 1:fractWeight = 20;candle=BarsNo*4; break;

case 2:fractWeight = 10;candle=BarsNo*8; break;

}

i=candle;

int timeFrame = timeFrames[tf];

while(i>0)

{

fractVal = NormalizeDouble(iFractals(NULL,timeFrame, MODE_UPPER,i),4); //verificam daca avem fractal UP

if (fractVal > 0)

{

fractTime = iTime(NULL,timeFrames[tf],i);

InserareInterior(cap,fractVal,fractWeight,fractTime);

}

fractVal = NormalizeDouble(iFractals(NULL, timeFrame, MODE_LOWER,i),4); //verificam daca avem fractal DOWN

if (fractVal > 0)

{

fractTime = iTime(NULL,timeFrames[tf],i);

InserareInterior(cap,fractVal,fractWeight,fractTime);

}

i–;

} //end fractal cycle

} // end tf cycle

}

//––––––––––––––––––––––––––

void InserareInterior(Fractal* &cap, double fvalue, int fweight, int ftime)

{

// Alocare si initializare nod

Fractal* fract = new Fractal;

fract.value = fvalue;

fract.weight = fweight;

fract.time = ftime;

fract.next = NULL;

if (cap == NULL)

cap = fract;

else

if(cap.value >= fvalue)

{

if(cap.value == fvalue){ delete(fract);return;}

if (cap.value != fvalue)

{

fract.next = cap;

//Print("inserare",fract.value," ",fract.weight);

cap = fract;

}

}

else

{

Fractal* p;

for (p=cap; p.next != NULL && p.next.value < fvalue ; p=p.next);

if( p.next != NULL && p.next.value == fvalue ){ delete(fract);return;}

if( p.next != NULL && p.next.value != fvalue)

{

fract.next = p.next;

//Print("inserare",fract.value," ",fract.weight);

p.next = fract;

//delete(p);

}

if( p.next == NULL )

{

fract.next = NULL;

//Print("inserare",fract.value," ",fract.weight);

p.next = fract;

}

}

}

void Afisare(Fractal* cap)

{

while( cap != NULL )

{

//Print("stergere",cap.value," ",cap.weight);

cap = cap.next;

}

}

void Stergere(Fractal* cap)

{

Fractal* p;

while(true)

{

if(cap == NULL)

{

delete(cap);

break;

}

else

{

p=cap;

//Print("stergere",cap.value," ",cap.weight);

cap=cap.next;

delete(p);

}

}

}

double Max(Fractal* cap)

{

if(cap.next == NULL ) return cap.value;

else

{

Fractal* p;

for (p = cap; p.next != NULL ; p=p.next);

return p.value;

}

}

//––––––––––––––––––––––––––

void CalculSR()

{

int min,max;

int arrayDim;

int element;

double arraySR[]; //Vector intermediar cu toate nivelele potentiale SR

//–– Initializare vector intermediar la dimensiunea necesara

if ( prim != NULL )

{

min = NormalizeDouble(prim.value * 10000,0);

max = NormalizeDouble(Max(prim) * 10000,0);

//Print("MIN ",min," MAX ",max);

}

arrayDim = max-min+2;

ArrayResize(arraySR,arrayDim); // Redimensionare la dimensiunea necesara

arraySR[0]=min-1; // Primul element din array este un index pentru celelalte elemente

//––––––––––––––––––––––––

//–– Populare Vector intermediar cu toate nivelele SR relative la interval

int count,i;

double limitaINF,limitaSUP;

double suma,sumaGR, mediaARP;

Fractal* p;

for (i=min; i<max-Interval+2;i++)

{

limitaINF = (double)i/10000;

limitaSUP = (double)(i+Interval-1)/10000;

p = prim;

suma = 0;

sumaGR = 0;

count = 0;

while ( p != NULL && p.value <=limitaSUP)

{

if (p.value>=limitaINF)

{

suma+=p.value*p.weight;

sumaGR+=p.weight;

count++;

}

p=p.next;

}

if ( count>0)

{

mediaARP=suma/sumaGR;

element = NormalizeDouble(mediaARP*10000,0)-arraySR[0];

arraySR[element]=(double)sumaGR;

}

}

//––––––––––––––––––––––––

/*

for (i=min; i<=max;i++)

{

element = i-arraySR[0];

//Print(arraySR[element]);

}

*/

bool avemFractal;

int nrNivele = 0;

ArrayFree(niveleSR);

//–– Populare array niveleSR[] cu lista finala de nivele de Suport si Rezistenta

for (i=1; i<=max-arraySR[0];i++)

{

if ( arraySR[i] > 0 && arraySR[i] >= 80 )

{

avemFractal = true;

for(int j=1; j<=FractNo;j++)

{

if ( (i-j>0 && arraySR[i-j] >= arraySR[i]) || arraySR[i+j] >= arraySR[i] ) { avemFractal = false; break; }

}

if ( avemFractal == true )

{

ArrayResize(niveleSR,nrNivele+1);

niveleSR[nrNivele] = (double)(i+arraySR[0])/10000;

nrNivele++;

}

}

}

//––––––––––––––––––––––––––

//AfisareSR();

// AfisareIntensitati();

/*

string ObjName;

for ( int k=min;k<=max;k++)

{

element = k-arraySR[0];

if(arraySR[element]>0)

{

int val = arraySR[element];

double StartX = Time[1];

double StartY = (double)k/10000;

double EndX = Time[1+val/10];

double EndY = StartY;

ObjName = DoubleToStr(k,0);

ObjectCreate(0,ObjName,OBJ_TREND,0,StartX,StartY,EndX,EndY);

ObjectSet(ObjName,OBJPROP_RAY,0);

ObjectSet(ObjName,OBJPROP_COLOR,Red);

}

}

*/

}

//––––––––––––––––––––––––––

void AfisareSR()

{

int dim = ArraySize(niveleSR);

string ObjName;

double nivel;

ObjectsDeleteAll(0,OBJ_TREND);

for (int i=0; i<dim; i++)

{

nivel = niveleSR[i];

double StartX = Time[1];

double StartY = nivel;

double EndX = Time[BarsNo*8];

double EndY = StartY;

ObjName = DoubleToStr(nivel,4);

ObjectCreate(0,ObjName,OBJ_TREND,0,StartX,StartY,EndX,EndY);

ObjectSet(ObjName,OBJPROP_RAY,0);

ObjectSet(ObjName,OBJPROP_COLOR,Red);

}

}

double UltimulFractal()

{

double fractValUP,fractValLOW;

int i = 0;

while ( true )

{

fractValUP = NormalizeDouble(iFractals(NULL,30, MODE_UPPER,i),4); //verificam daca avem fractal UP

if ( fractValUP > 0 ) return fractValUP;

fractValLOW = NormalizeDouble(iFractals(NULL, 30, MODE_LOWER,i),4); //verificam daca avem fractal DOWN

if ( fractValLOW > 0 ) return fractValLOW;

i++;

}

}

double CalculSUP()

{

int dimSR = ArraySize(niveleSR);

for ( int i = 0; i<dimSR ; i++ )

{

if ( Bid < niveleSR[i] )

{

double nivel = niveleSR[i];

double StartX = Time[1];

double StartY = nivel;

double EndX = Time[100];

double EndY = StartY;

string ObjName = DoubleToStr(nivel,4);

ObjectCreate(0,ObjName,OBJ_TREND,0,StartX,StartY,EndX,EndY);

ObjectSet(ObjName,OBJPROP_RAY,0);

ObjectSet(ObjName,OBJPROP_COLOR,Red);

return niveleSR[i];

}

}

return 0;

}

//–––––––––––––––––––––

double CalculINF()

{

int dimSR = ArraySize(niveleSR);

for ( int i = dimSR-1; i>=0 ; i– )

{

if ( Bid > niveleSR[i] )

{

double nivel = niveleSR[i];

double StartX = Time[1];

double StartY = nivel;

double EndX = Time[100];

double EndY = StartY;

string ObjName = DoubleToStr(nivel,4);

ObjectCreate(0,ObjName,OBJ_TREND,0,StartX,StartY,EndX,EndY);

ObjectSet(ObjName,OBJPROP_RAY,0);

ObjectSet(ObjName,OBJPROP_COLOR,Red);

return niveleSR[i];

}

}

return 0;

}

Anexa 3.4 PlasareComenzi.mqh

void BuySignal()

{

double volume, SL, TP;

SL = CalculINF()-100*Point;

TP = CalculSUP();

volume = CalculVolum(SL,TP);

SendBuyOrder(volume,SL,TP);

}

void SellSignal()

{

double volume, SL, TP;

SL = CalculSUP()+100*Point;

TP = CalculINF();

volume = CalculVolum(SL,TP);

SendSellOrder(volume,SL,TP);

}

void SendBuyOrder(double volume, double SL, double TP)

{

int Ticket;

while(true)

{

Ticket = OrderSend(NULL,OP_BUY,volume,Ask,3,SL,TP,NULL,12345,0,Blue);

if (Ticket>=0) return;

else // avem eroare

{

if(Errors(GetLastError())==false)// Daca eroarea e critica

return;

}

}

}

void SendSellOrder(double volume, double SL, double TP)

{

int Ticket;

while(true)

{

Ticket = OrderSend(NULL,OP_SELL,volume,Bid,3,SL,TP,NULL,12345,0,Red);

if (Ticket>=0) return;

else // avem eroare

{

if(Errors(GetLastError())==false)// Daca eroarea e critica

return;

}

}

}

bool Errors(int Error)

{

if(Error==0)

return(false); // Nu exista eroare

//––––––––––––––––––––– 3 –

switch(Error)

{ // Erori non- critice

case 129: // Pret Gresit

case 135: // Pretul s-a schimbat

RefreshRates(); // Se reinoieste informatia

return(true);

case 136: // Nu exista cotatii, se asteapta un nou tick

while(RefreshRates()==false) // inaintea unui nou Tick

Sleep(1); // se face un delay

return(true);

case 146: // Subsistemul de tranzactionare este ocupat

Sleep(500); // solutie simpla

RefreshRates(); // Se reinnoieste informatia

return(true);

// Erori critice:

case 2 : // Eroare comuna

case 5 : // Versiune invechita a terminalului client

case 64: // Cont blocat

case 133: // Tranzactionare interzisa

default: // Alte variante

return(false); // Eroare critica

}

//––––––––––––––––––––– 4 –

}

double CalculVolum(double SL, double TP)

{

double raport,procent,pipValue,volum,equity;

raport = NormalizeDouble(MathAbs(TP-Bid)/MathAbs(SL-Bid),2);

procent = NormalizeDouble(VolumePercentage/raport/100,3); //procent din equity

Print(procent);

pipValue = (AccountEquity() * procent) / NormalizeDouble(MathAbs(SL-Bid)*10000,0) ;

volum = NormalizeDouble(pipValue/10,2);

return(volum);

}

Anexa 4.1 Rezultatele Optimizarii USD/CHF

Anexa 4.3 Rezultatele testelor pentru perechea USD/CAD

BIBLIOGRAFIE

Similar Posts

  • Permutari Circulare

    Prin permutarea circulară a n elemente (obiecte ) () scrise în această ordine, înțelegem trecerea unui element în următorul, închizând astfel un cerc imaginar, adică și scrise numai în această ordine. A.1.Sumă circulară de trei obiecte a,b,c În cadrul exercițiilor cu sumă circulară se vor face trecerile: Astfel pot să apară diverse situații, ca de…

  • Aplicatii Multimedia In Retele de Calculatoare

    Cuprins Capitolul 1. Rețele de calculatoare ………………………………………………………………….2 Noțiuni generale despre rețelele de calculatoare ……………………………………………..2 Modelul OSI ………………………………………………………………………………………………3 Modelul TCP/IP ………………………………………………………………………………………….5 Paralelă între OSI și TCP/IP …………………………………………………………………………6 Încapsularea datelor …………………………………………………………………………………….7 Tipuri de rețele de calculatoare………………………………………………………………………8 Capitolul 2. Rețele wireless …………………………………………………………………………………10 2.1 Generalități despre rețelele fără fir…………………………………………………………………10 2.2 Funcționarea unei rețele wireless …………………………………………………………………..11 2.3 Topologii ale rețelelor…

  • Proiectarea Unei Retele de Calculatoare Pentru Internet

    UNIVERSITATEA DE VEST “VASILE GOLDIS” DIN ARAD FACULTATEA DE ȘTIINTE ALE NATURII INGINERIE ȘI INFORMATICĂ LUCRARE DE LICENȚĂ Proiectarea unei rețele de calculatoare pentru internet Conducător stiințific Popescu Marius Absolvent Böszörményi Tibor Arad 2015 Cuprins Introducere……………………………………………………………………………………………………5 Capitolul 1.Proiectare rețelei……………………………………………………….6 1.1.Normele de proiectare a rețelei…………………………………………………7 1.2.Rețeaua LAN……………………………………………………………………8 1.3.Documentare pentru realizarea proiectului…………………………………..…8 Capitolul 2.Locul de amplasare a…

  • Sistemul de Operare Windows 7

    Sistemul de operare Windows 7 Sistemul de operare este un ansamblu de module de programe ale unui sistem și de proceduri manuale,care asigurã o utilizare eficientã a resurselor sistemului de calcul. Windows 7 este una dintre versiunile de Microsoft Windows, reprezentând sistemul de operare ce a fost produs de compania Microsoft, în scopul utilizării acestuia,…

  • Initierea Si Planificarea Unui Sistem Informatic

    LISTA FIGURILOR, IMAGINILOR ȘI TABELELOR Figura 1 – Poziția sistemului informatic în cadrul sistemului informațional Figura 2 – Evoluția în timp a sistemelor informatice Figura 3 – Relația SI – SIA Figura 4 – Sistem informatic, subsisteme, aplicații, programe Figura 5 – Sistemul întreprindere Tabelul 1 – Variante de proiecte INTRODUCERE În zilele noastre toate…

  • Modelarea Traficului Urban Prin Intermediul Programelor Software

    CUPRINS 1 Introducere 2 Sisteme de semnalizare rutieră utilizate în cadrul programelor de modelare și simulare 2.1 Noțiuni despre drum 2.1.1 Părțile componente ale drumului public 2.1.2 Profilurile drumului public 2.1.3 Clasificarea drumurilor publice 2.2 Semnalizarea rutieră 2.2.1 Indicatoare 2.2.2 Marcaje 2.2.3 Semne de semnalizare luminoasă sau sonoră 2.2.4 Alte dispozitive special 3 Sisteme de…