Populære Indlæg

Redaktørens Valg - 2019

MQL4: Skrivning af en transaktionskopimaskine til MetaTrader4

God eftermiddag venner!

Du har bestemt mere end én gang brug for at kopiere transaktioner fra en af ​​dine terminaler til en anden. For eksempel, hvis du har brug for at åbne den samme position på forskellige konti eller med flere mæglere. Manuelt tager dette arbejde nogen tid, hvilket kan gemmes, hvis du overdrager denne rutinemæssige opgave til tekstforfatteren. Derudover kan tekstforfatteren selv skrive.

I dag lærer vi, hvordan man skriver en simpel transaktionskopimaskine til MT4. Kopieringsprocessen i artiklen implementeres gennem et fælles filmappe, så den samme tilgang kan bruges til at overføre enhver information mellem flere MT4 / MT5-terminaler på en pc.

Generel idé

Ideen er dette. Alle terminaler, der er installeret på computeren, deler et bibliotek med hinanden. I det generelle bibliotek opretter udbyderen en fil med alle åbne positioner. Klientterminalen læser data fra en fil og åbner de nødvendige positioner.

Denne tilgang blev valgt på grund af dens alsidighed og lette implementering. Men dette er langt fra en universel løsning, fordi der i nogle situationer er behov for hurtig og høj gennemstrømning, som filerne ikke kan give. Ikke desto mindre vil dette være tilstrækkeligt til at kopiere konventionel handel.

Hovedproblemet for alle kopister er statssynkronisering. Først og fremmest er vi nødt til på en eller anden måde at forbinde ordren på klienten med den ordre, der er åbnet af udbyderen. For at gøre dette, som en unik identifikator for ordren (magisk nummer), bruger vi udbyderens ordrekort. I dette tilfælde kan ordrebilletten ændres, hvis kun en del af stillingen blev lukket, og denne sag også skal behandles.

struct Params {int-konto; char symbolSYMBOL_LEN; int-billet; int magi; int type; dobbelt lydstyrke; dobbelt sl; dobbelt tp; dobbelt egenkapital; };

Så skriver guiden alle aktive positioner til en fælles fil. Klienten læser derefter disse data og opretter sin egen kopi af filen i det lokale bibliotek. For at arbejde, er vi nødt til at oprette funktioner til læsning og skrivning med mulighed for at få adgang til delte og lokale mapper.

I denne implementering går EA ind i en endeløs løkke, indtil den får adgang til filen. Deling af en delt fil leveres ikke. Så vi redder os fra underordnede data, som klienten fejlagtigt kan tage for et handelssignal.

ugyldig skrivning (strengnavn, Params & a, bool local = false) {int h; gør {h = lokalt? FileOpen (navn, FILE_WRITE | FILE_BIN): FileOpen (navn, FILE_WRITE | FILE_BIN | FILE_COMMON); if (GetLastError ()! = 0) Sleep (DELAY); } while (h == INVALID_HANDLE); FileWriteArray (h, a); FileClose (h); } ugyldigt læst (strengnavn, Params & a, bool local = false) {int h; gør {h = lokalt? FileOpen (navn, FILE_READ | FILE_BIN): FileOpen (navn, FILE_READ | FILE_BIN | FILE_COMMON); if (GetLastError ()! = 0) Sleep (DELAY); } while (h == INVALID_HANDLE); FileReadArray (h, a); FileClose (h); }

Filnavne oprettes i initialiseringsfunktionen. Navnet på den delte fil er det samme for alle, navnet på den lokale sikkerhedskopi er nummeret på handelskontoen. Vi ringer straks til backup-metoden, som opretter en lokal post (stadig tom) med positioner i terminalmappen.

void create () {account = AccountNumber (); backupName = IntegerToString (AccountNumber ()); sharedName = "delt"; sikkerhedskopi (); }

Faktisk opretter backup-metoden en sikkerhedskopifil, gennem hvilken vi derefter tjekker for ændringer i åbne positioner.

void backup () {skriv (backupName, delt, sandt); }

Der er også en mulighed for at læse fra en fil, hvor antallet af gemte positioner returneres.

int backup (Params & a) {læse (backupName, a, sandt); return ArraySize (a); }

Der er de samme metoder til deling af positioner. "Træk" - for at hente positionsdata fra den delte fil, "del" - for at skrive ændringer til den delte fil. I "share" er der support til flere udbydere. For at eliminere konflikten mellem flere hovedkonti, der prøver på at få adgang til en enkelt fil, identificeres hver udbyder med kontonummeret.

int pull (Params & a) {læse (delt navn, a); return ArraySize (a); } void share () {Params orders, temp; læse (delt navn, ordrer); // læse de delte positioner int szO = ArraySize (ordrer); int szP = ArraySize (positioner); int szTemp = ArrayResize (temp, 0, szO + szP); // kopier alle "udenlandske" ordrer i den midlertidige matrix for (int i = 0; i

Metoden “åbnet” returnerer de aktuelle åbne positioner på kontoen. I begyndelsen sagde jeg, at med delvis lukning ændrer Metatrader ordrebilletten, og den gamle skriver i kommentaren til den nye. Derfor, så kunden forstår, at dette ikke er en ny ordre, husker vi den gamle billet ved at skrive den i ”magi” -feltet.

for (int i = total-1; i> = 0; i--) {if (OrderSelect (i, SELECT_BY_POS) && OrderType () <= 1) {sz = ArrayResize (positioner, sz + 1); char sa; StringToCharArray (OrderSymbol (), sa); ArrayCopy (positionssz-1.symbol, sa); positionssz-1.ticket = OrderTicket (); c = OrderComment (); positionssz-1.magic = StringToInteger (StringSubstr (c, StringFind (c, "#") + 1)); positionssz-1.volume = OrderLots (); positionssz-1.sl = OrderStopLoss (); positionssz-1.tp = OrderTakeProfit (); positionssz-1.type = OrderType (); positionssz-1.equity = ækv. }}

Copyistens hovedfunktion, direkte kopiering af aftaler, implementeres ved hjælp af "mergeAndTrade" -metoden. Se den nøjagtige implementering i den fulde kilde. Kort sagt, alt hvad vi gør er at sammenligne den sidste lokale sikkerhedskopi med den delte fil. Hvis der er sket ændringer i den generelle fil, ændrer vi de aktuelle positioner eller åbner nye.

For nemheds skyld returnerer en instans af klassen en markør til sig selv, når du ringer til alle de grundlæggende funktioner.

TradeCopier * func () {... returner GetPointer (dette); }

Organiseringen af ​​udbyderens og kopimaskinsarbejdet implementeres således med kun en kodelinje med et sekventielt opkald af de nødvendige funktioner.

ugyldigt OnTimer () {if (CopierType == SLAVE) {copier.mergeAndTrade (); } andet hvis (CopierType == MASTER) {copier.opened (). share (); }}

Endelig skaber vi en lille statisk handelsklasse "Handel", der ikke gør noget andet, da den åbner og ændrer positioner. Ideelt set er implementering af en smart fejlhåndterer nødvendig i tilfælde af stærk uoverensstemmelse af tilbud. Synkroniseringslogikken kan også konfigureres på en anden måde i tilfælde af en afbrydelse eller et lukket marked. Åbn for eksempel kun sene signaler til en bedre pris.

Du kan også vælge, hvordan du kopierer bind. Et fast volumen kopieres en til en, uanset størrelsen af ​​indskud. Den dynamiske volumen kopieres multiple af egenkapitalstørrelsen på klienten. Det vil sige, hvis en position på 0,1 partier med et depositum på $ 100 er åben hos udbyderen, vil en transaktion med et volumen på 0,2 partier åbnes for en klient med et depositum på $ 200.

Hvis partiet er dynamisk, beregner vi forholdet mellem den aktuelle kontots egenkapital og masterens konto og multiplicerer denne værdi med ordrens volumen. Glem heller ikke at normalisere lydstyrken.

dobbelt v = LotType == DYNAMIC? normalizeLot (CharArrayToString (p.symbol), eq / p.equity * p.volume): p.volume; statisk dobbelt normalizeLot (streng symbol, dobbelt parti) {dobbelt lotMin = SymbolInfoDouble (symbol, SYMBOL_VOLUME_MIN); dobbelt lotMax = SymbolInfoDouble (symbol, SYMBOL_VOLUME_MAX); dobbelt lotStep = SymbolInfoDouble (symbol, SYMBOL_VOLUME_STEP); dobbelt c = 1,0 / lotStep; dobbelt l = gulv (parti * c) / c; hvis (l lotMax) l = lotMax; retur l; }

For at starte kopiering kaster vi eksperten på diagrammet og vælger typen af ​​kopimaskine - Master eller Slave. Antallet af udbydere og klienter er ikke begrænset - du kan kopiere transaktioner fra flere konti af enhver type til alle reelle / demo-konti.

Konklusion

Så på dette tidspunkt implementeret:

  • Pålidelighed ved overførsel - filer bruges ikke samtidig af forskellige processer, mens hver klient har et snapshot af aktuelle positioner;
  • Kopiering af et fast og relativ volumen af ​​positioner, support til ændring af stopniveauer og delvis lukning;
  • Mulighed for brug på ethvert antal MT4 / MT5-terminaler, med et ubegrænset antal udbydere / klienter.

Ulemperne inkluderer:

  • Læsningshastighed er ikke ideel til skalpning, kopiering af hak og andre handlinger, der kræver minimal forsinkelse;
  • Diskbelastning - jo lavere forsinkelse, desto oftere overskrives filen.

Se videoen: Robot Building Tutorials #6 - Intro to MQL4 (December 2019).

Efterlad Din Kommentar