IndianTrailingStopLoss/GrayMatrix/Database.mqh
super.admin 88be02cad4 convert
2025-05-30 15:00:53 +02:00

305 lines
29 KiB
MQL5

//+------------------------------------------------------------------+
//| Database.mqh |
//| GrayMatrix |
//| |
//+------------------------------------------------------------------+
#property copyright "Jay Davis"
#property link "https://512jay.github.io"
#property version "1.00"
input string DatabaseName = "DATABASE"; //\AppData\Roaming\MetaQuotes\Terminal\Common\DATABASE
struct DBMqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type
ulong magic; // Expert Advisor ID (magic number)
ulong order; // Order ticket
string symbol; // Trade symbol
double volume; // Requested volume for a deal in lots
double price; // Price
double stoplimit; // StopLimit level of the order
double sl; // Stop Loss level of the order
double tp; // Take Profit level of the order
ulong deviation; // Maximal possible deviation from the requested price
ENUM_ORDER_TYPE type; // Order type
ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type
ENUM_ORDER_TYPE_TIME type_time; // Order expiration type
datetime expiration; // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type)
string comment; // Order comment
ulong position; // Position ticket
ulong position_by; // The ticket of an opposite position
};
//+------------------------------------------------------------------+
//| Creates a new database if it does not exist |
//+------------------------------------------------------------------+
bool CreateDataBase(string filename, bool createNew = false)
{
if(!createNew)
return false;
Print(__FUNCTION__, " ", filename);
//--- open/create the database in the common terminal folder
int db=DatabaseOpen(filename, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE | DATABASE_OPEN_COMMON);
if(db==INVALID_HANDLE)
{
Print("DB: ", filename, " open failed with code ", GetLastError());
return false;
}
//--- create the MqlTradeRequest table
if(!CreateTableMqlTradeRequest(db, createNew))
{
Print("Table created");
DatabaseClose(db);
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Opens the deals table and returns the handle |
//+------------------------------------------------------------------+
int OpenDatabase(string filename)
{
//--- open/create the database in the common terminal folder
int db=DatabaseOpen(filename, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE | DATABASE_OPEN_COMMON);
if(db==INVALID_HANDLE)
{
Print("DB: ", filename, " open failed with code ", GetLastError());
return -1;
}
return db;
}
//+------------------------------------------------------------------+
//| Inserts a MqlTradeRequest into DB without a db handle |
//+------------------------------------------------------------------+
bool InsertMqlTradeRequest(MqlTradeRequest & request)
{
MqlTradeRequest temp = request;
bool inserted = false;
int db = OpenDatabase(DatabaseName);
inserted = InsertMqlTradeRequest(db, request);
if(!inserted)
{
Print("Insert failed taking measures\nCreated database: ", DatabaseName);
if(!DatabaseTableExists(db, "MQLTRADEREQUEST"))
if(CreateTableMqlTradeRequest(db, true))
{
db = OpenDatabase(DatabaseName);
inserted = InsertMqlTradeRequest(db, temp);
}
}
DatabaseClose(db);
return inserted;
}
//+------------------------------------------------------------------+
//| Add a request to the database table with handle |
//+------------------------------------------------------------------+
bool InsertMqlTradeRequest(int database, MqlTradeRequest & r)
{
// --- lock the database before executing transactions
DatabaseTransactionBegin(database);
string request_text = StringFormat("INSERT INTO MQLTRADEREQUEST ("
"ACTION," //%d
"MAGIC_NUMBER," //%d
"ORDER_TICKET," //%d
"SYMBOL," //%s
"VOLUME," //%G
"PRICE," //%G
"STOPLIMIT," //%G
"STOPLOSS," //%G
"TAKEPROFIT,"//%G
"DEVIATION,"//%d
"TYPE,"//%d
"TYPE_FILLING,"//%d
"TYPE_TIME,"//%d
"EXPIRATION,"//%d
"COMMENT," //%s.
"POSITION,"//%d
"POSITION_BY)"//%d
"VALUES (%d,%d,%d,'%s',%G,%G,%G,%G,%G,%d,%d,%d,%d,%d,'%s',%d,%d);",
r.action, r.magic, r.order, r.symbol, r.volume, r.price, r.stoplimit,
r.sl, r.tp, r.deviation, r.type, r.type_filling, r.type_time,
r.expiration, r.comment, r.position, r.position_by);
//Print(r.action, r.magic, r.order, r.symbol, r.volume, r.price, r.stoplimit, r.sl, r.tp, r.comment, r.position, r.position_by, TimeCurrent());
if(!DatabaseExecute(database, request_text)) //request_text
{
PrintFormat("%s: failed to insert MqlTradeRequest %s with code %d",
__FUNCTION__, r.symbol, GetLastError());
//--- roll back all transactions and unlock the database
DatabaseTransactionRollback(database);
PrintFormat("%s: DatabaseExecute() failed with code %d", __FUNCTION__, GetLastError());
return(false);
}
else
{
Print("Inserted: ",
EnumToString((ENUM_ORDER_TYPE)r.type), " magic #",
r.magic, " \"", r.comment, "\" on ", r.symbol, " with (vol ", r.volume,
") at (price:", r.price, ") (SL:", r.sl, ") (TP:", r.tp, ") at ", TimeCurrent());
}
//--- all transactions have been performed successfully - record changes and unlock the database
DatabaseTransactionCommit(database);
return(true);
}
//+------------------------------------------------------------------+
//| Create the MqlTradeRequest table |
//+------------------------------------------------------------------+
bool CreateTableMqlTradeRequest(int database, bool createNew = false)
{
//--- if the MQLTRADEREQUEST table already exists, delete it
if(createNew && !DeleteTable(database, "MQLTRADEREQUEST"))
{
return(false);
}
//--- check if the table exists
if(!DatabaseTableExists(database, "MQLTRADEREQUEST"))
//--- create the table
if(!DatabaseExecute(database, "CREATE TABLE MQLTRADEREQUEST("
"ACTION INT," // Trade operation type
"MAGIC_NUMBER INT," // Expert Advisor ID (magic number)
"ORDER_TICKET INT," // Order ticket
"SYMBOL CHAR(25)," // Trade symbol
"VOLUME REAL," // Requested volume for a deal in lots
"PRICE REAL," // Price
"STOPLIMIT REAL," // StopLimit level of the order
"STOPLOSS REAL," // Stop Loss level of the order
"TAKEPROFIT REAL," // Take Profit level of the order
"DEVIATION INT," // Maximal possible deviation from the requested price
"TYPE INT," // Order type
"TYPE_FILLING INT," // Order execution type
"TYPE_TIME INT," // Order expiration type
"EXPIRATION DATETIME," // Order expiration time
"COMMENT TINYTEXT," // Order comment
"POSITION INT," // Position ticket
"POSITION_BY INT);")) // The ticket of an opposite position
{
Print("DB: create the MQLTRADEREQUEST table failed with code ", GetLastError());
return(false);
}
//--- the table has been successfully created
Print("Created MQLTRADEREQUEST table.");
return(true);
}
//+------------------------------------------------------------------+
//| Delete a table with the specified name from the database |
//+------------------------------------------------------------------+
bool DeleteTable(int database, string table_name)
{
if(!DatabaseExecute(database, "DROP TABLE IF EXISTS "+table_name))
{
Print("Failed to drop the DEALS table with code ", GetLastError());
return(false);
}
//--- the table has been successfully deleted
return(true);
}
//+------------------------------------------------------------------+
//| Queries the database with given string, returns a request handle |
//+------------------------------------------------------------------+
int QueryDatabase(int databaseHandle, string requestText = "SELECT COUNT(*) FROM MQLTRADEREQUEST;")
{
int request = DatabasePrepare(databaseHandle, requestText);
if(request == INVALID_HANDLE)
{
Print("DB: ", requestText, " request failed with code ", GetLastError());
DatabaseClose(databaseHandle);
return -1;
}
return request;
}
//+------------------------------------------------------------------+
//| Returns the number of rows in the given table |
//+------------------------------------------------------------------+
int GetTableSize(string databaseName, string table = "MQLTRADEREQUEST")
{
int db = OpenDatabase(databaseName);
string requestText = StringFormat("SELECT COUNT(*) FROM %s;", table);
int request=QueryDatabase(db, requestText);
// get table size
int size;
DatabaseRead(request);
if(!DatabaseColumnInteger(request, 0, size))
{
Print("DatabaseRead() failed with code ", GetLastError());
DatabaseFinalize(request);
DatabaseClose(db);
return -1;
}
//--- remove the query after use
DatabaseFinalize(request);
DatabaseClose(db);
return size;
}
//+------------------------------------------------------------------+
//| Returns true if the database has more updates |
//+------------------------------------------------------------------+
bool CheckForDB_Update(long & rowId, string databaseName, string table = "MQLTRADEREQUEST")
{
long currentRowID, db;
db = OpenDatabase(databaseName);
currentRowID = GetTableSize(databaseName, table);
if(currentRowID > rowId)
return true;
return false;
}
//+------------------------------------------------------------------+
//| Downloads the latest updates from the database |
//+------------------------------------------------------------------+
bool GetDB_Updates(long &rowID, string databaseName, MqlTradeRequest &array[], string table = "MQLTRADEREQUEST")
{
DBMqlTradeRequest temp;
MqlTradeRequest fromDB[];
int db = OpenDatabase(databaseName);
string requestText = StringFormat("SELECT * FROM %s WHERE ROWID > %d;", table, rowID);
int request = QueryDatabase(db, requestText);
//Print(databaseName, " ", requestText, " handle of a request ", request);
for(int i=0; DatabaseReadBind(request, temp); i++)
{
int size = ArraySize(fromDB);
ArrayResize(fromDB, size + 1);
fromDB[i].action = (ENUM_TRADE_REQUEST_ACTIONS) temp.action;
fromDB[i].comment = temp.comment;
fromDB[i].deviation = temp.deviation;
fromDB[i].expiration = temp.expiration;
fromDB[i].magic = temp.magic;
fromDB[i].order = temp.order;
fromDB[i].position = temp.position;
fromDB[i].position_by = temp.position_by;
fromDB[i].price = temp.price;
fromDB[i].sl = temp.sl;
fromDB[i].stoplimit = temp.stoplimit;
fromDB[i].tp = temp.tp;
fromDB[i].type = (ENUM_ORDER_TYPE) temp.type;
fromDB[i].type_filling = (ENUM_ORDER_TYPE_FILLING) temp.type_filling;
fromDB[i].type_time = (ENUM_ORDER_TYPE_TIME) temp.type_time;
fromDB[i].volume = temp.volume;
fromDB[i].symbol = temp.symbol;
}
//--- delete request after use
DatabaseFinalize(request);
DatabaseClose(db);
int size = ArraySize(fromDB);
rowID += size;
ArrayFree(array);
for(int i=0; i < size; i++)
{
ArrayResize(array, ArraySize(array) + 1);
array[i].action = fromDB[i].action; // = (ENUM_TRADE_REQUEST_ACTIONS) temp.action;
array[i].comment = fromDB[i].comment; // = temp.comment;
array[i].deviation = fromDB[i].deviation; // = temp.deviation;
array[i].expiration = fromDB[i].expiration; // = temp.expiration;
array[i].magic = fromDB[i].magic; // = temp.magic;
array[i].order = fromDB[i].order; // = temp.order;
array[i].position = fromDB[i].position; // = temp.position;
array[i].position_by = fromDB[i].position_by; // = temp.position_by;
array[i].price = fromDB[i].price; // = temp.price;
array[i].sl = fromDB[i].sl; // = temp.sl;
array[i].stoplimit = fromDB[i].stoplimit; // = temp.stoplimit;
array[i].tp = fromDB[i].tp; // = temp.tp;
array[i].type = fromDB[i].type; // = (ENUM_ORDER_TYPE) temp.type;
array[i].type_filling = fromDB[i].type_filling; // = (ENUM_ORDER_TYPE_FILLING) temp.type_filling;
array[i].type_time = fromDB[i].type_time; // = (ENUM_ORDER_TYPE_TIME) temp.type_time;
array[i].volume = fromDB[i].volume; // = temp.volume;
array[i].symbol = fromDB[i].symbol; // = temp.symbol;
}
return size > 0;
}
//+------------------------------------------------------------------+