Price Data Components
Orders Execution
Miscellaneous
0
Views
0
Downloads
0
Favorites
snowseed-lib
//:adic:
double standardLot = 1;
// Value of the take profit, on a chart:
// dTp = Bid - dTakeProfit;
// or
// dTp = Ask + dTakeProfit;
double dTp = 0;
// Used to deside, if this is the beginning of a new bar.
int nBars;
// An expert runs 10 * nMagic seconds after the bar end
// This way we reduce competition between experts and
// avoid deadlocks
int nDelaySeconds = 10;
// Slippage
int nSlip = 5;
// Used to calculate the size of a lot, if bUseMm is
// set to 0, the lot size is always 0.1
// We strongly recommend that you use your own
// money management system, this is just a simple
// placeholder
double dProfit = 0;
// Used to figure out if we have enough money to trade
// We strongly recommend that you use your own
// money management system, this is just a simple
// placeholder
double dInitAmount = 1000;
// A standart lot size
double dLotSize = 1; //lotSize; //0.1;
// Magic number. Unique for a combination of expert -
// currency - timeframe
int nMagic = 0;
// Report is not part of the trading, but only a
// function to write transactions to a file. We
// do it once a day
bool bReportDone = false;
// This variable contains 0, or the magic number
// of currently trading expert
string strTradeSemaphore = "TradeSemaphore";
// ------
/* This function creates a file with the name,
that is unique for an expert-currency-timeframe,
and writes trading history in it.
Note, that we only same the profit of operation(s)
here. If you want to save additional information,
like order open dates or swaps, you need to modify
the code below.
The strFileName contains the file name prefix,
usually it is the name of an expert.
*/
void Report(string strFileName, int nMagic,
bool& bReportDone)
{
// Do it only during run time trading
if(IsTesting())
return;
// Save once a day, at 0 hours nMagic / 2 minutes
if(Hour() == 0 && Minute() >= nMagic / 2)
{
// Make sure it only happens once, even
// if we have 2 or more ticks satisfying
// the condition above
if(bReportDone == false)
{
int hFile = FileOpen(strFileName + "_" + Symbol() + "_" + Period() + ".rpt", FILE_BIN | FILE_WRITE, ',');
string str = "CloseDateTime,Buy,Sell\r\n";
FileWriteString(hFile, str, StringLen(str));
// Write the entire trading history to the
// file.
// Note: make sure all trading history is
// available (MT4-Terminal-Account History)
for(int nCnt = 0; nCnt < HistoryTotal();
nCnt++)
{
OrderSelect(nCnt, SELECT_BY_POS, MODE_HISTORY);
if(OrderMagicNumber() == nMagic && OrderType() <= OP_SELL && OrderSymbol() == Symbol())
{
str = TimeToStr(OrderCloseTime(), TIME_DATE|TIME_MINUTES);
if(OrderType() == OP_BUY) str = str + "," + OrderProfit() + ",0";
else
str = str + ",0," + OrderProfit();
str = str + " \r\n ";
FileWriteString(hFile, str,
StringLen(str));
}
}
FileFlush(hFile);
FileClose(hFile);
bReportDone = true;
}
}
else if(Hour() != 0) // Reset the flag
bReportDone = false;
}
// ------
// A simple placeholder for a real money management
// algorythm. In expert, set bUseMm to false or
// true. A default lot size is 0.1.
double GetLotSize(double dInitFraction = 0.1,
double dProfitFraction = 0.1)
{
double dLot = standardLot; //0.1;
if(bUseMm)
{
dLot = (dInitFraction * dInitAmount + dProfitFraction * dProfit) / 1000;
dLot = MathFloor(dLot * 10) / 10;
if(dLot < standardLot) dLot = standardLot;
}
return(dLot);
}
// ------
/* Buy() and Sell() functions use dStopLoss and
dTakeProfit, that are assigned in the expert.
We are going to try to open an order for 10 times,
because sometimes the server or the Internet
connection fails.
Note the call to SaveComment() function. If the
order was not opened, when you think it should
be, you may check the corresponding file in
experts/files directory. It will give you the
error number and some additional hints on what
happened.
Note, that it is possible to use more than one
magic number with the same
expert-currency-timeframe, in which case
you need to explicitely pass it as a
nMagicNumber parameter.
dLot is a coefficient (a multiplier) used to
increase the lot size, usually, you will use
it for trading contests, or if you are
overconfident in the performance (drawdowns)
of your expert.
*/
int Sell(string strExpertName, double dLot = 0,
int nMagicNumber = -1)
{
int nResult = -1;
if(nMagicNumber == -1)
nMagicNumber = nMagic;
if(dLot == 0)
dLotSize = GetLotSize();
else
dLotSize = dLot * GetLotSize();
// Note, that this is a simple placeholder for a
// real money management algorythm. We will discuss
// money management in a separate article.
if(AccountFreeMargin() < dLotSize * dInitAmount
|| AccountFreeMargin() < 500)
return(nResult);
double dTp;
if(dTakeProfit == 0)
dTp = 0;
else
dTp = Bid - dTakeProfit;
// We try 10 times
for(int nTry = 0; nTry < 10; nTry++)
{
SaveComment(" \r\n " + Day() + "." + Month() + "." + Year() + " " + Hour() + ":" +
Minute() + ":" + Seconds());
SaveComment(" Trying to sell, attempt " + nTry + " \r\n ");
SaveComment("\r\nAsk: " + Ask + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit + " \r\n ");
double vAdicStopLoss;
if (dStopLoss == 0) vAdicStopLoss = 0;
else {
if (dStopLoss >= 1) {
vAdicStopLoss = Bid + dStopLoss*Point;
}
else vAdicStopLoss = Bid + dStopLoss;
}
nResult = OrderSend(Symbol(), OP_SELL, dLotSize, Ask, nSlip, vAdicStopLoss, dTp, strExpertName, nMagicNumber, 0, Aqua);
//nResult = OrderSend(Symbol(), OP_SELL, dLotSize, Bid, nSlip, Bid + dStopLoss*Point, dTp, strExpertName, nMagicNumber, 0, OrangeRed);
// Wait 10 seconds before the next try.
Sleep(10000);
// If trade failed, refresh rates and try again
if(nResult != -1)
{
SaveComment(" successfull\r\n");
break;
}
else
{
SaveComment(" failed, error " + GetLastError()
+ " \r\n ");
RefreshRates();
}
}
// If all 10 attempts failed, write additional info
// to the report file
if(nResult == -1)
{
int nError = GetLastError();
Alert(strExpertName + " sell error: " + nError + " \r\n " + Bid + ", " + vAdicStopLoss + ", " + dTp);
SaveComment(strExpertName + " sell error: " + nError + " \r\n " + Bid + ", " + vAdicStopLoss + ", " + dTp);
}
return(nResult);
}
// ------
// The structure of Buy() is similar to Sell(),
// see Sell() for comments
int Buy(string strExpertName, double dLot = 0,
int nMagicNumber = -1)
{
int nResult = -1;
if(nMagicNumber == -1)
nMagicNumber = nMagic;
if(dLot == 0)
dLotSize = GetLotSize();
else
dLotSize = dLot * GetLotSize();
if(AccountFreeMargin() < dLotSize * dInitAmount
|| AccountFreeMargin() < 500)
return(nResult);
double dTp;
if(dTakeProfit == 0)
dTp = 0;
else
dTp = Ask + dTakeProfit;
for(int nTry = 0; nTry < 10; nTry++)
{
SaveComment(" \r\n " + Day() + "." + Month() + "." + Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
SaveComment(" Trying to buy, attempt " + nTry + " \r\n ");
SaveComment("\r\nBid: " + Bid + ", StopLoss: " + dStopLoss + ", TakeProfit: " + dTakeProfit);
double vAdicStopLoss;
if (dStopLoss == 0) vAdicStopLoss = 0;
else {
if (dStopLoss >= 1) {
vAdicStopLoss = Ask - dStopLoss*Point;
}
else vAdicStopLoss = Ask - dStopLoss;
}
nResult = OrderSend(Symbol(), OP_BUY, dLotSize, Ask, nSlip, vAdicStopLoss, dTp, strExpertName, nMagicNumber, 0, Aqua);
//:adic:nResult = OrderSend(Symbol(), OP_BUY, dLotSize, Ask, nSlip, Ask - dStopLoss*Point, dTp, strExpertName, nMagicNumber, 0, Aqua);
Sleep(10000);
if(nResult != -1)
{
SaveComment(" successfull\r\n");
break;
}
else
{
SaveComment(" failed, error " + GetLastError() + " \r\n ");
RefreshRates();
}
}
if(nResult == -1)
{
int nError = GetLastError();
Alert(strExpertName + " buy error: " + nError + " \r\n " + Ask + ", " + vAdicStopLoss + ", " + dTp);
SaveComment(strExpertName + " buy error: " + nError + " \r\n " + Ask + ", " + vAdicStopLoss + ", " + dTp);
}
return(nResult);
}
// ------
/* We use this function to modify orders. It uses
dTrailingStop, assigned in the expert. When the
price goes away from the stop loss more than 5
points (from the stop loss to stop loss + 5 points),
we move the stop closer to the price.
*/
void ModifyOrders()
{
if(dTrailingStop == 0)
return;
// Scan all opened orders, looking for an
// order with "our" magic number
for(int nCnt = 0; nCnt < OrdersTotal();
nCnt++)
{
OrderSelect(nCnt, SELECT_BY_POS,
MODE_TRADES);
if(OrderMagicNumber() == nMagic)
{
if(OrderType() == OP_BUY)
{
if(OrderStopLoss() < Bid -
dTrailingStop - 5 * Point)
{
OrderModify(OrderTicket(),
OrderOpenPrice(),
Bid - dTrailingStop,
OrderTakeProfit(),
0, Aqua);
// Note: we assume, that there
// is only one opened order with
// this magic number in a time.
// If it is not so, comment the
// "break".
break;
}
}
if(OrderType() == OP_SELL)
{
if(OrderStopLoss() > Ask +
dTrailingStop + 5 * Point)
{
OrderModify(OrderTicket(),
OrderOpenPrice(),
Ask + dTrailingStop,
OrderTakeProfit(),
0, OrangeRed);
break;
}
}
}
}
}
// ------
// This function determines if this is the beginning
// of a new bar. Note, that in order to avoid conflicts
// between experts, we wait few seconds after the bar
// start, the delay is unique for each expert-currency-
// timeframe
bool IsBarEnd()
{
bool bIsBarEnd = false;
if(nBars != Bars)
{
if(IsTesting() || (!IsTesting() &&
CurTime() > Time[0] + nMagic * nDelaySeconds))
{
bIsBarEnd = true;
nBars = Bars;
}
}
return(bIsBarEnd);
}
// ------
/* The magic number of the currently trading expert
(or 0) is stored in the global variable. In a cycle,
our expert tries to set its magic number to this global
variable, and when successfull, exits the cycle.
*/
void CheckTradeSemaphore()
{
if(!IsTesting())
{
while(!IsStopped())
{
GlobalVariableSetOnCondition(
strTradeSemaphore, nMagic,
0.0);
if(GlobalVariableGet(strTradeSemaphore)
== nMagic)
break;
Sleep(1000);
}
RefreshRates();
}
}
// ------
/* Attempts to close an order, for 10 times.
Comments written to the file with SaveComment()
will help you to debug the expert, if it fails
to close an order.
*/
void CloseBuy(string strExpertName)
{
int nTicket = OrderTicket();
SaveComment(" \r\n \tAttempting to close long position, ticket: " + nTicket + " \r\n ");
for(int nTry = 0; nTry < 10; nTry++)
{
SaveComment(Day() + "." + Month() + "." +
Year() + " " + Hour() + ":" + Minute() + ":" + Seconds());
int nResult = OrderClose(OrderTicket(), OrderLots(), Bid, nSlip, Aqua);
Sleep(10000);
if(nResult == -1)
{
int nError = GetLastError();
Alert(strExpertName + ", error: " + nError);
SaveComment(strExpertName + ", error: " + nError);
}
bool bClosed = true;
for(int nOrderNo = OrdersTotal() - 1;
nOrderNo >= 0; nOrderNo--)
{
OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
if(OrderTicket() == nTicket)
{
bClosed = false;
break;
}
}
if(bClosed == true)
{
SaveComment(
" \r\n \tNo more orders with this ticket No");
break;
}
else
{
SaveComment(" \r\n \tOrder with this ticket still present, trying again");
RefreshRates();
}
}
}
// ------
// Same logic as in CloseBuy()
void CloseSell(string strExpertName)
{
int nTicket = OrderTicket();
SaveComment(" \r\n \tAttempting to close short position, ticket: " + nTicket + " \r\n ");
for(int nTry = 0; nTry < 10; nTry++)
{
SaveComment(Day() + "." + Month() + "." + Year() +
" " + Hour() + ":" + Minute() + ":" + Seconds());
int nResult = OrderClose(OrderTicket(),
OrderLots(), Ask, nSlip, OrangeRed);
Sleep(10000);
if(nResult == -1)
{
int nError = GetLastError();
Alert(strExpertName + ", error: " + nError);
SaveComment(strExpertName + ", error: " + nError);
}
bool bClosed = true;
for(int nOrderNo = OrdersTotal() - 1;
nOrderNo >= 0; nOrderNo--)
{
OrderSelect(nOrderNo, SELECT_BY_POS, MODE_TRADES);
if(OrderTicket() == nTicket)
{
bClosed = false;
break;
}
}
if(bClosed == true)
{
SaveComment(" \r\n \tNo more orders with this ticket No");
break;
}
else
{
SaveComment(" \r\n \tOrder with this ticket still present, trying again");
RefreshRates();
}
}
}
// ------
// Open a file with unique file name, add a string
// to the end of this file
void SaveComment(string strComment)
{
if(!IsTesting())
{
int hFile = FileOpen("__test_" + strExpert +
"_" + Symbol() + ".txt",
FILE_BIN | FILE_READ | FILE_WRITE, '\t');
FileSeek(hFile, 0, SEEK_END);
FileWriteString(hFile, strComment,
StringLen(strComment));
FileClose(hFile);
}
}
// ------
// Delete pending order, logic is the same as in
// CloseBuy()
int DeletePending()
{
int nResult = -1;
for(int nTry = 0; nTry < 10; nTry++)
{
SaveComment(" \r\n " + Day() + "." + Month() +
"." + Year() + " " + Hour() + ":" +
Minute() + ":" + Seconds());
SaveComment(" Trying to delete pending " +
OrderTicket() + ", attempt " + nTry + " \r\n ");
nResult = OrderDelete(OrderTicket());
Sleep(10000);
if(nResult != -1)
{
SaveComment(" successfull\r\n");
break;
}
else
SaveComment(" failed, error " +
GetLastError() + " \r\n ");
}
if(nResult == -1)
{
int nError = GetLastError();
Alert(strExpert + " delete pending, error: "
+ nError + " \r\n ");
SaveComment(strExpert +
" delete pending, error: " + nError + " \r\n ");
}
return(nResult);
}
Comments
Markdown Formatting Guide
# H1
## H2
### H3
**bold text**
*italicized text*
[title](https://www.example.com)

`code`
```
code block
```
> blockquote
- Item 1
- Item 2
1. First item
2. Second item
---