#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; }
发表评论