SQLogTrades.mqh

#define ACTIVE_ORDERS_SIZE 50
#define CLOSED_ORDERS_SIZE 20

struct order_info {
   int ticket;                // ticket number of the order
   double atr;                // ATR atthe time of oredr open
   double mfe;                // mfe of the order
   double mae;                // mae of the order
   bool processed;
};
 
order_info activeOrders[ACTIVE_ORDERS_SIZE];      //array of active orders
order_info closedOrders[CLOSED_ORDERS_SIZE];      //array of closed orders
bool processedOrders[ACTIVE_ORDERS_SIZE];         //each order has its bool flag that indicates if the order was processed in the last call of sqLogTrades function

int activeOrdersCount = 0;
int closedOrderNextIndex = 0;
string logFileName;
int tradeMagicNumber;
int atrPeriod;
int lastHistoryOrdersCount;
int closedOrdersCount;

//+------------------------------------------------------------------+

void sqInitLog(string fileName, int magicNumber, int _atrPeriod){
   Print("LogTrades init");
   
   logFileName = fileName;
   tradeMagicNumber = magicNumber;
   atrPeriod = _atrPeriod; 

   closedOrdersCount = 0;
   lastHistoryOrdersCount = OrdersHistoryTotal();
   
   for(int i=0; i<ACTIVE_ORDERS_SIZE; i++) {
      activeOrders[i].ticket = -1;   
   }   
}

//+------------------------------------------------------------------+

void sqLogTrades() {
   processOpenOrders();
   processClosedOrders();
   deleteNonProcessedOnArray(activeOrders);
}

//+------------------------------------------------------------------+

void sqCloseLog(){
   Print("Closing log...");
   
   processClosedOrders();
   
   if(closedOrdersCount > 0) {
      saveBufferToFile(closedOrdersCount, closedOrders);
   }
    //saveOrders(closedOrders, closedOrderNextIndex);
    //saveOrders(activeOrders, orderNextIndex);
}

//+------------------------------------------------------------------+

void processOpenOrders() {
   int ticketNo, orderIndex;
   double profit;
   
   resetProcessed(activeOrders);
   
   // go through all open orders
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) && (tradeMagicNumber == 0 || tradeMagicNumber == OrderMagicNumber())) {
         ticketNo = OrderTicket();
         profit = OrderProfit();
         
         orderIndex = findTicketInArray(ticketNo, activeOrders);
         if(orderIndex == -1) {
            // it is a new order, doesn't exist in array yet
            addNewOpenOrder(ticketNo, iATR(NULL, 0, atrPeriod, 0));
            
         } else {
            // existing order, update MAE/MFE
            activeOrders[orderIndex].mae = MathMin(profit, activeOrders[orderIndex].mae);
            activeOrders[orderIndex].mfe = MathMax(profit, activeOrders[orderIndex].mfe);
            activeOrders[orderIndex].processed = true;
         }          
      }
   }
}


//+------------------------------------------------------------------+

void processClosedOrders() {

   int orderIndex;
   
   for(int i=OrdersHistoryTotal()-1; i>=lastHistoryOrdersCount; i--){
      if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY) && (tradeMagicNumber == 0 || tradeMagicNumber == OrderMagicNumber())){
         int ticketNo = OrderTicket();
         
         //Print("Closed order # ", ticketNo);
         
         orderIndex = findTicketInArray(ticketNo, activeOrders);
         if(orderIndex == -1) {
            // this closed order was not found in the array of open orders, so we don't have its MAE/MFE.
            // it was probably opened and closed within one tick
            saveOrder(ticketNo, iATR(NULL, 0, atrPeriod, 0), 0, 0);
            
         } else {
            saveOrder(ticketNo, activeOrders[orderIndex].atr, activeOrders[orderIndex].mae, activeOrders[orderIndex].mfe);
            
            // "delete" this active order from buffer
            activeOrders[orderIndex].ticket = -1;
            activeOrders[orderIndex].processed = true;
         }          
      }
   }
   
   lastHistoryOrdersCount = OrdersHistoryTotal();
}

//+------------------------------------------------------------------+

void saveOrder(int ticketNo, double atr, double mae, double mfe) {
   if(closedOrdersCount == CLOSED_ORDERS_SIZE) {
      // there is no space in the buffer, save it to the file
      saveBufferToFile(closedOrdersCount, closedOrders);
      closedOrdersCount = 0;
   }
   
   closedOrders[closedOrdersCount].ticket = ticketNo;
   closedOrders[closedOrdersCount].atr = atr;
   closedOrders[closedOrdersCount].mae = mae;
   closedOrders[closedOrdersCount].mfe = mfe;
      
   closedOrdersCount++;
}

//+------------------------------------------------------------------+

void saveBufferToFile(int numberOfRecords, order_info& ordersArray[]) {
   int handle = FileOpen(logFileName, FILE_CSV | FILE_READ | FILE_WRITE, ",");
   if(handle > 0) {
      FileSeek(handle, 0, SEEK_END);
       
      for(int i=0; i<numberOfRecords; i++){
         int ticketNo = ordersArray[i].ticket;
           
         if (OrderSelect(ticketNo, SELECT_BY_TICKET, MODE_HISTORY) == true){
            string tradeType = "TRADE";
            string entryDate = TimeToStr(OrderOpenTime(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);
            double entryPrice = OrderOpenPrice();
            string exitDate = TimeToStr(OrderCloseTime(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);
            double exitPrice = OrderClosePrice();
            string symbol = OrderSymbol();
              
            int type;
            if(OrderType() == OP_BUY || OrderType() == OP_BUYLIMIT || OrderType() == OP_BUYSTOP) {
               type = 1;
            } else {
               type = -1;
            }
              
            double size = OrderLots();
            int magicNumber = OrderMagicNumber();
            string comment = OrderComment();
            double profit = OrderProfit() + OrderCommission() + OrderSwap();           //we must calculate net profit!
            double atr = ordersArray[i].atr;
            double mfe = MathMax(ordersArray[i].mfe, profit);
            double mae = MathMin(ordersArray[i].mae, profit);
               
            FileWrite(handle, tradeType, entryDate, entryPrice, exitDate, exitPrice, symbol, type, size, magicNumber, comment, profit, atr, mfe, mae);
               
            //Print("Order ", ticketNo, " saved.");

            FileClose(handle);
         } else {
            Print("Unable to select an order with ticket number ", ticketNo);
         }
      } 
   } else {
      //Print("Unable to open file.");
   }
}

//+------------------------------------------------------------------+

void resetProcessed(order_info& ordersArray[]) {
   int size = ArraySize(ordersArray);
   
   for(int i=0; i<size; i++){
      ordersArray[i].processed = false;
   }
}

//+------------------------------------------------------------------+

void deleteNonProcessedOnArray(order_info& ordersArray[]) {
   int size = ArraySize(ordersArray);
   
   for(int i=0; i<size; i++){
      if(ordersArray[i].processed == false) {
         ordersArray[i].ticket = -1;
      }
   }
}

//+------------------------------------------------------------------+

int findTicketInArray(int ticketNo, order_info& ordersArray[]) {
   int size = ArraySize(ordersArray);
   
   for(int i=0; i<size; i++){
      if(ordersArray[i].ticket == ticketNo){
         return i;
      }
   }
   return -1;
}

//+------------------------------------------------------------------+

int findFirstFreeIndex(order_info& ordersArray[]) {
   int size = ArraySize(ordersArray);
   
   for(int i=0; i<size; i++){
      if(ordersArray[i].ticket == -1){
         return i;
      }
   }
   
   return -1;
}

//+------------------------------------------------------------------+

void addNewOpenOrder(int ticketNo, double atr) {
   int orderIndex = findFirstFreeIndex(activeOrders);
   if(orderIndex < 0) {
      //Print("There is no free space in open orders buffer to add new order!");
      return;
   }
            
   activeOrders[orderIndex].ticket = ticketNo;
   activeOrders[orderIndex].atr = atr;
   activeOrders[orderIndex].mae = 0;
   activeOrders[orderIndex].mfe = 0;
   activeOrders[orderIndex].processed = true;
}
本博客所有文章如无特别注明均为原创。作者:天泓评测
分享到:更多

相关推荐

发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(0)