Adaptive Trading Systems
http://www.mql5.com/en/articles/143
//+------------------------------------------------------------------+
//| CStrategyMA.mqh |
//| Copyright 2010, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link "http://www.mql5.com"
#include <CSampleStrategy.mqh>
//+------------------------------------------------------------------+
//| Class CStrategyMA for implementation of virtual trading |
//| by the strategy based on moving average |
//+------------------------------------------------------------------+
class CStrategyMA : public CSampleStrategy
{
protected:
int m_handle; // handle of the Moving Average (iMA) indicator
int m_period; // period of the Moving Average indicator
double m_values[]; // array for storing values of the indicator
public:
// initialization of the strategy
int Initialization(int period,bool virtual_trade_flag);
// deinitialization of the strategy
int Deinitialization();
// checking trading conditions and opening virtual positions
bool CheckTradeConditions();
};
//+------------------------------------------------------------------+
//| Strategy Initialization Method |
//+------------------------------------------------------------------+
int CStrategyMA::Initialization(int period,bool virtual_trade_flag)
{
// set period of the moving average
m_period=period;
// set specified flag of virtual trading
SetVirtualTradeFlag(virtual_trade_flag);
//set indexation of arrays like the one of timeseries
ArraySetAsSeries(m_rates,true);
ArraySetAsSeries(m_values,true);
//create handle of the indicator
m_handle=iMA(_Symbol,_Period,m_period,0,MODE_EMA,PRICE_CLOSE);
if(m_handle<0)
{
Alert("Error of creation of the MA indicator - error number: ",GetLastError(),"!!");
return(-1);
}
return(0);
}
//+------------------------------------------------------------------+
//| Strategy Deinitialization Method |
//+------------------------------------------------------------------+
int CStrategyMA::Deinitialization()
{
Position_CloseOpenedPosition(m_position);
IndicatorRelease(m_handle);
return(0);
};
//+------------------------------------------------------------------+
//| Checking trading conditions and opening virtual positions |
//+------------------------------------------------------------------+
bool CStrategyMA::CheckTradeConditions()
{
RecalcPositionProperties(m_position);
double p_close;
// get history data of the last three bars
if(CopyRates(_Symbol,_Period,0,3,m_rates)<0)
{
Alert("Error of copying history data - error:",GetLastError(),"!!");
return(false);
}
// Copy the current price of closing of the previous bar (it is bar 1)
p_close=m_rates[1].close; // close price of the previous bar
if(CopyBuffer(m_handle,0,0,3,m_values)<0)
{
Alert("Error of copying buffers of the Moving Average indicator - error number:",GetLastError());
return(false);
}
// buy condition 1: MA rises
bool buy_condition_1=(m_values[0]>m_values[1]) && (m_values[1]>m_values[2]);
// buy condition 2: previous price is greater than the MA
bool buy_condition_2=(p_close>m_values[1]);
// sell condition 1: // MA falls
bool sell_condition_1=(m_values[0]<m_values[1]) && (m_values[1]<m_values[2]);
// sell condition 2: // previous price is lower than the MA
bool sell_condition_2=(p_close<m_values[1]);
int new_state=0;
if(buy_condition_1 && buy_condition_2) new_state=SIGNAL_OPEN_LONG;
if(sell_condition_1 && sell_condition_2) new_state=SIGNAL_OPEN_SHORT;
if((GetSignalState()==SIGNAL_OPEN_SHORT) && (buy_condition_1 || buy_condition_2)) new_state=SIGNAL_CLOSE_SHORT;
if((GetSignalState()==SIGNAL_OPEN_LONG) && (sell_condition_1 || sell_condition_2)) new_state=SIGNAL_CLOSE_LONG;
if(GetSignalState()!=new_state)
{
SetSignalState(new_state);
}
return(true);
};
=========================================================================
//+------------------------------------------------------------------+//| CSampleStrategy.mqh |//| Copyright 2010, MetaQuotes Software Corp. |//| http://www.mql5.com |//+------------------------------------------------------------------+#property copyright "Copyright 2010, MetaQuotes Software Corp."#property link "http://www.mql5.com"#include <Object.mqh>#define POSITION_NEUTRAL 0 // no position#define POSITION_LONG 1 // long position#define POSITION_SHORT -1 // short position#define SIGNAL_OPEN_LONG 10 // signal to open a long position#define SIGNAL_OPEN_SHORT -10 // signal to open a short position#define SIGNAL_CLOSE_LONG -1 // signal to close a long position#define SIGNAL_CLOSE_SHORT 1 // signal to close a short position//+------------------------------------------------------------------+//| Structure for storing the parameters of virtual position |//+------------------------------------------------------------------+struct virtual_position { string symbol; // symbol int direction; // direction of the virtual position (0-no open position,+1 long,-1 short) double volume; // volume of the position in lots double profit; // current profit of the virtual position on points double stop_loss; // Stop Loss of the virtual position double take_profit; // Take Profit of the virtual position datetime time_open; // date and time of opening the virtual position datetime time_close; // date and time of closing the virtual position double price_open; // open price of the virtual position double price_close; // close price of the virtual position double price_highest; // maximum price during the life of the position double price_lowest; // minimal price during the lift of the position double entry_eff; // effectiveness of entering double exit_eff; // effectiveness of exiting double trade_eff; // effectiveness of deal }; //+------------------------------------------------------------------+//| Class CSampleStrategy |//+------------------------------------------------------------------+class CSampleStrategy: public CObject { protected: int m_strategy_id; // Strategy ID string m_strategy_symbol; // Symbol string m_strategy_name; // Strategy name string m_strategy_comment; // Comment MqlTick m_price_last; // Last price MqlRates m_rates[]; // Array for current quotes bool m_virtual_trade_allowed; // Flag of allowing virtual trading int m_current_signal_state; // Current state of strategy double m_current_trade_volume; // Number of lots for trading double m_initial_balance; // Initial balance (set in the constructor, default value is 10000) int m_sl_points; // Stop Loss int m_tp_points; // Take Profit virtual_position m_position; // Virtual position virtual_position m_deals_history[]; // Array of deals int m_virtual_deals_total; // Total number of deals double m_virtual_balance; // "Virtual" balance double m_virtual_equity; // "Virtual" equity double m_virtual_cumulative_profit; // cumulative "virtual" profit double m_virtual_profit; // profit of the current open "virtual" position //checks and closes the virtual position by stop levels if it is necessary bool CheckVirtual_Stops(virtual_position &position); // recalculation of position and balance void RecalcPositionProperties(virtual_position &position); // recalculation of open virtual position in accordance with the current prices void Position_RefreshInfo(virtual_position &position); // open virtual short position void Position_OpenShort(virtual_position &position); // closes virtual short position void Position_CloseShort(virtual_position &position); // opens virtual long position void Position_OpenLong(virtual_position &position); // closes the virtual long position void Position_CloseLong(virtual_position &position); // closes open virtual position void Position_CloseOpenedPosition(virtual_position &position); // adds closed position to the m_deals_history[] array (history of deals) void AddDealToHistory(virtual_position &position); //calculates and returns the recommended volume that will be used in trading virtual double MoneyManagement_CalculateLots(double trade_volume); public: // constructor void CSampleStrategy(); // destructor void ~CSampleStrategy(); //returns the current size of virtual balance double GetVirtualBalance() { return(m_virtual_balance); } //returns the current size of virtual equity double GetVirtualEquity() { return(m_virtual_equity); } //returns the current size of virtual profit of open position double GetVirtualProfit() { return(m_virtual_profit); } //sets Stop Loss and Take Profit in points void Set_Stops(int tp,int sl) {m_tp_points=tp; m_sl_points=sl;}; //sets the current volume in lots void SetLots(double trade_volume) {m_current_trade_volume=trade_volume;}; //returns the current volume in lots double GetCurrentLots() { return(m_current_trade_volume); } // returns strategy name string StrategyName() { return(m_strategy_name); } // returns strategy ID int StrategyID() { return(m_strategy_id); } // returns the comment of strategy string StrategyComment() { return(m_strategy_comment); } // sets the details of strategy (symbol, name and ID of strategy) void SetStrategyInfo(string symbol,string name,int id,string comment); // set the flag of virtual trading (allowed or not) void SetVirtualTradeFlag(bool pFlag) { m_virtual_trade_allowed=pFlag; }; // returns flag of allowing virtual trading bool IsVirtualTradeAllowed() { return(m_virtual_trade_allowed); }; // returns the current state of strategy int GetSignalState(); // sets the current state of strategy (changes virtual position if necessary) void SetSignalState(int state); // changes virtual position in accordance with the current state void ProceedSignalState(virtual_position &position); // sets the value of cumulative "virtual" profit void SetVirtualCumulativeProfit(double cumulative_profit) { m_virtual_cumulative_profit=cumulative_profit; }; //returns the effectiveness of strategy () double StrategyPerformance(); //updates position data void UpdatePositionData(); //closes open virtual position void CloseVirtualPosition(); //returns the direction of the current virtual position int PositionDirection(); //virtual function of initialization virtual int Initialization() {return(0);}; //virtual function of checking trade conditions virtual bool CheckTradeConditions() {return(false);}; //virtual function of deinitialization virtual int Deinitialization() {return(0);}; //saves virtual deals to a file void SaveVirtualDeals(string file_name); };
//+------------------------------------------------------------------+ //| Constructor of the CSampleStrategy class | //+------------------------------------------------------------------+ void CSampleStrategy::CSampleStrategy() { ZeroMemory(m_position); // clear m_position m_virtual_cumulative_profit=0; // cumulative virtual profit m_virtual_profit=0; // virtual profit m_current_trade_volume=0.1; // default volume in lots m_strategy_id=0; // default ID=0 m_strategy_name="Sample Strategy"; // default is "Sample Strategy" m_current_signal_state=0; // current state of strategy m_virtual_trade_allowed=true; // virtual trading is allowed on default m_initial_balance=10000; // initial virtual balance m_virtual_balance=m_initial_balance; // current virtual balance m_virtual_equity=m_initial_balance; // current virtual equity m_sl_points=0; // default Stop Loss value (in points) m_tp_points=0; // default Take Profit value (in points) } //+------------------------------------------------------------------+ //| Destructor of the CSampleStrategy class | //+------------------------------------------------------------------+ void CSampleStrategy::~CSampleStrategy() { //zeroize array sizes ArrayResize(m_rates,0); ArrayResize(m_deals_history,0); } //+------------------------------------------------------------------+ //| Function of updating position data | //+------------------------------------------------------------------+ void CSampleStrategy::UpdatePositionData() { RecalcPositionProperties(m_position); } //+------------------------------------------------------------------+ //| Function of closing virtual position | //+------------------------------------------------------------------+ void CSampleStrategy::CloseVirtualPosition() { Position_CloseOpenedPosition(m_position); } //+------------------------------------------------------------------+ //| Returns current direction of position | //+------------------------------------------------------------------+ int CSampleStrategy::PositionDirection() { return(m_position.direction); } //+------------------------------------------------------------------+ //| Function returns the recommended volume for strategy in lots | //| The current volume is passed to it a a parameter | //| Volume can be set depending on: | //| current m_virtual_balance and m_virtual_equity | //| current statistics of deals (that is stored in m_deals_history) | //| or any other thing you want | //| If the change of volume is not required in the strategy | //| we can return the passed volume: return(trade_volume); | //+------------------------------------------------------------------+ double CSampleStrategy::MoneyManagement_CalculateLots(double trade_volume) { //return what has been obtained return(trade_volume); } //+------------------------------------------------------------------+ //| The StrategyPerformance function of effectiveness of strategy | //+------------------------------------------------------------------+ double CSampleStrategy::StrategyPerformance() { //returns the effectiveness of strategy //in this case it's the difference between the amount //of equity at the moment and the initial balance //i.e. how much money the strategy has earned double performance=(m_virtual_equity-m_initial_balance); return(performance); /* //if there were deals performed, then multiple the result of three next deals by this value if(m_virtual_deals_total>0) { int avdeals=MathRound(MathMin(3,m_virtual_deals_total)); double sumprofit=0; for(int j=0; j<avdeals; j++) { sumprofit+=m_deals_history[m_virtual_deals_total-1-j].profit; } sumprofit=sumprofit/avdeals; performance=performance*sumprofit; } return(performance); */ } //+------------------------------------------------------------------+ //| Set the details of strategy (name, ID, comment) | //+------------------------------------------------------------------+ void CSampleStrategy::SetStrategyInfo(string symbol,string name,int id,string comment) { //symbols m_strategy_symbol=symbol; //ID m_strategy_id=id; //name m_strategy_name=name; //comment m_strategy_comment=comment; //symbol of position m_position.symbol=m_strategy_symbol; } //+------------------------------------------------------------------+ //| "Closes" the current open virtual position, | //| copies its parameters and adds | //| it to the array of virtual deals m_deals_history | //+------------------------------------------------------------------+ void CSampleStrategy::AddDealToHistory(virtual_position &position) { //request the size of the array of virtual deals m_virtual_deals_total=ArraySize(m_deals_history); //increase it by 1 m_virtual_deals_total++; //increase the size of array m_deals_history by 1 ArrayResize(m_deals_history,m_virtual_deals_total); //copy the position properties to the last element of the array m_deals_history[m_virtual_deals_total-1].symbol=position.symbol; m_deals_history[m_virtual_deals_total-1].direction=position.direction; m_deals_history[m_virtual_deals_total-1].volume=position.volume; m_deals_history[m_virtual_deals_total-1].stop_loss=position.stop_loss; m_deals_history[m_virtual_deals_total-1].take_profit=position.take_profit; m_deals_history[m_virtual_deals_total-1].profit = position.profit; m_deals_history[m_virtual_deals_total-1].volume = position.volume; m_deals_history[m_virtual_deals_total-1].time_open=position.time_open; m_deals_history[m_virtual_deals_total-1].time_close = position.time_close; m_deals_history[m_virtual_deals_total-1].price_open = position.price_open; m_deals_history[m_virtual_deals_total-1].price_close= position.price_close; m_deals_history[m_virtual_deals_total-1].price_highest= position.price_highest; m_deals_history[m_virtual_deals_total-1].price_lowest = position.price_lowest; m_deals_history[m_virtual_deals_total-1].entry_eff= position.entry_eff; m_deals_history[m_virtual_deals_total-1].exit_eff = position.exit_eff; m_deals_history[m_virtual_deals_total-1].trade_eff= position.trade_eff; //current profit of position m_virtual_profit=position.profit; //increase the cumulative profit by the size of the position that is cosed m_virtual_cumulative_profit=m_virtual_cumulative_profit+m_virtual_profit; //zeroize the direction of position (no position) position.direction=0; //zeroize the profit of position position.profit=0; } //+----------------------------------------------------------------------+ //| Checks and closes virtual position by stop levels if it is necessary | //+----------------------------------------------------------------------+ bool CSampleStrategy::CheckVirtual_Stops(virtual_position &position) { if(position.direction==0) {return(false);} //if there is a position, check if it should be closed by stop levels if(position.direction==POSITION_LONG) { if((position.stop_loss>0.0) && (position.price_close<=position.stop_loss)) { //Print("Close LONG: Stop Loss: ",position.stop_loss," Price:",position.price_close); Position_CloseLong(position); return(true); } if((position.take_profit>0.0) && (position.price_close>=position.take_profit)) { //Print("Close LONG: Take Profit: ",position.take_profit," Price:",position.price_close); Position_CloseLong(position); return(true); }; } if(position.direction==POSITION_SHORT) { if((position.stop_loss>0.0) && (position.price_close>=position.stop_loss)) { //Print("Close SHORT: Stop Loss: ",position.stop_loss," Price:",position.price_close); Position_CloseShort(position); return(true); } if((position.take_profit>0.0) && (position.price_close<=position.take_profit)) { //Print("Close SHORT: ",position.take_profit," Price:",position.price_close); Position_CloseShort(position); return(true); } } return(false); } //+------------------------------------------------------------------+ //| Recalculates parameters of open virtual position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_RefreshInfo(virtual_position &position) { //request the last quotes by the symbols of position SymbolInfoTick(position.symbol,m_price_last); //if there is a position, recalculate its parameters if(position.direction!=0) { position.time_close=0; position.price_highest=MathMax(position.price_highest,m_price_last.ask); position.price_lowest=MathMin(position.price_lowest,m_price_last.bid); double xfactor; if((position.price_highest-position.price_lowest)==0) { //Print("BID=ASK?","Bid=",m_price_last.bid," Ask=",m_price_last.ask); return; } xfactor=1.0/(position.price_highest-position.price_lowest); //for a long position if(position.direction==POSITION_LONG) { position.price_close=m_price_last.bid; position.entry_eff=(position.price_highest-position.price_open)*xfactor; position.exit_eff=(position.price_close-position.price_lowest)*xfactor; position.trade_eff=(position.price_close-position.price_open)*xfactor; position.profit=position.volume*(position.price_close-position.price_open)/_Point; } //for a short position if(position.direction==POSITION_SHORT) { position.price_close=m_price_last.ask; position.entry_eff=(position.price_open-position.price_lowest)*xfactor; position.exit_eff=(position.price_highest-position.price_close)*xfactor; position.trade_eff=(position.price_open-position.price_close)*xfactor; position.profit=position.volume*(position.price_open-position.price_close)/_Point; } CheckVirtual_Stops(position); } } //+------------------------------------------------------------------------+ //| Recalculation of the properties of position and of the current balance | //+------------------------------------------------------------------------+ void CSampleStrategy::RecalcPositionProperties(virtual_position &position) { //Refresh the parameters of open position Position_RefreshInfo(m_position); // if the position is open, refresh the profit if(m_position.direction!=0) { m_virtual_profit=m_position.profit; } //string s1="RecalcPositionProperties:"+StrategyName()+" "+m_virtual_equity+" Balance="+m_virtual_balance+" m_virtual_cumulative_profit="+m_virtual_cumulative_profit+" "+m_virtual_profit; //refresh the values of equity and balance m_virtual_equity=m_initial_balance+m_virtual_cumulative_profit+m_virtual_profit; m_virtual_balance=m_initial_balance+m_virtual_cumulative_profit; // s1=s1+" new value="+m_virtual_equity+" new balance="+m_virtual_balance; // Print(s1); } //+------------------------------------------------------------------+ //| Closes open short position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_CloseShort(virtual_position &position) { //exit if the virtual trading is prohibited if(!m_virtual_trade_allowed) {return;} //exit if the direction of virtual position doesn't correspond with POSITION_SHORT if(position.direction!=POSITION_SHORT){return;} //fix the time of closing the virtual position position.time_close=TimeCurrent(); //add the deal to the history and close the virtual position AddDealToHistory(position); } //+------------------------------------------------------------------+ //| Opens virtual long position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_OpenLong(virtual_position &position) { //exit if the virtual trading is prohibited if(!m_virtual_trade_allowed) {return;} //set the direction of the virtual position position.direction=POSITION_LONG; // calculate the volume according to Money Management m_current_trade_volume=MoneyManagement_CalculateLots(m_current_trade_volume); //set volume of the virtual position position.volume=m_current_trade_volume; //set the time of opening the virtual position position.time_open=TimeCurrent(); //set the price of opening the virtual position position.price_open=m_price_last.ask; //set Stop Loss of the virtual sell position if(m_sl_points>0) position.stop_loss=position.price_open+m_sl_points*_Point; else position.stop_loss=0; //set Take Profit of the virtual sell position if(m_tp_points>0) position.take_profit=position.price_open-m_tp_points*_Point; else position.take_profit=0; //Print("Position_OpenLong: SL=",position.stop_loss," TP=",position.take_profit); //set the current price of closing the virtual position (for the convenience of calculation) position.price_close=m_price_last.bid; //set the time of closing the virtual position position.time_close=0; //calculate profit position.profit=position.volume*(position.price_close-position.price_open)/_Point; //set the maximum price position.price_highest=m_price_last.ask; //set the minimum price position.price_lowest=m_price_last.bid; //update the properties of position in correspondence with the prices RecalcPositionProperties(position); } //+------------------------------------------------------------------+ //| Close the virtual buy position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_CloseLong(virtual_position &position) { //exit if the virtual trading is prohibited if(!m_virtual_trade_allowed) {return;} //exit if the direction of virtual position doesn't correspond with POSITION_LONG if(position.direction!=POSITION_LONG){return;} //fix the time of closing the virtual position position.time_close=TimeCurrent(); //add the deal to the history and close the virtual position AddDealToHistory(position); } //+------------------------------------------------------------------+ //| Opens virtual sell position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_OpenShort(virtual_position &position) { //exit if the virtual trading is prohibited if(!m_virtual_trade_allowed) {return;} //set the direction of the virtual position position.direction=POSITION_SHORT; // calculate the volume according to Money Management m_current_trade_volume=MoneyManagement_CalculateLots(m_current_trade_volume); //set volume of the virtual position position.volume=m_current_trade_volume; //set the time of opening the virtual position position.time_open=TimeCurrent(); //set the price of opening the virtual position position.price_open=m_price_last.bid; //set the current price of closing the virtual position (for the convenience of calculation) position.price_close=m_price_last.ask; //set Stop Loss of the virtual sell position if(m_sl_points>0) position.stop_loss=position.price_open+m_sl_points*_Point; else position.stop_loss=0; //set Take Profit of the virtual sell position if(m_tp_points>0) position.take_profit=position.price_open-m_tp_points*_Point; else position.take_profit=0; //Print("Position_OpenShort: SL=",position.stop_loss," TP=",position.take_profit); //set the time of closing the virtual position position.time_close=0; //calculate profit position.profit=position.volume*(position.price_open-position.price_close)/_Point; //set the maximum price position.price_highest=m_price_last.ask; //set the minimum price position.price_lowest=m_price_last.bid; //update the properties of position in correspondence with the prices RecalcPositionProperties(position); } //+------------------------------------------------------------------+ //| Closes open virtual position | //+------------------------------------------------------------------+ void CSampleStrategy::Position_CloseOpenedPosition(virtual_position &position) { if(position.direction!=POSITION_NEUTRAL) { if(position.direction==POSITION_SHORT) Position_CloseShort(position); if(position.direction==POSITION_LONG) Position_CloseLong(position); } } //+------------------------------------------------------------------+ //| Changes the "position" position in accordance with | //| the value of m_current_signal_state | //+------------------------------------------------------------------+ void CSampleStrategy::ProceedSignalState(virtual_position &position) { if(position.direction!=POSITION_NEUTRAL) // these is an open virtual position { switch(m_current_signal_state) { case SIGNAL_CLOSE_SHORT: { Position_CloseShort(position); break; } case SIGNAL_CLOSE_LONG: { Position_CloseLong(position); break;} } } else // no open virtual position { switch(m_current_signal_state) { case SIGNAL_OPEN_LONG: { Position_OpenLong(position); break; } case SIGNAL_OPEN_SHORT: { Position_OpenShort(position); break;} } } } //+------------------------------------------------------------------+ //| Returns the current state of strategy | //+------------------------------------------------------------------+ int CSampleStrategy::GetSignalState() { return(m_current_signal_state); } //+------------------------------------------------------------------+ //| Sets the current state of strategy | //| changes the virtual position if necessary | //+------------------------------------------------------------------+ void CSampleStrategy::SetSignalState(int state) { if(m_current_signal_state!=state) { m_current_signal_state=state; ProceedSignalState(m_position); } }; //+------------------------------------------------------------------+ //| Save all performed virtual deals to a file | //+------------------------------------------------------------------+ void CSampleStrategy::SaveVirtualDeals(string file_name) { //exit if there has been no trades if(m_virtual_deals_total==0) {return;}; //open a file for writing int filehandle=FileOpen(file_name,FILE_WRITE|FILE_CSV); //write headers of columns FileWrite(filehandle, "Symbol", "Direction", "Profit", "Volume", "OpenTime", "CloseTime", "OpenPrice", "ClosePrice", "HighestPrice", "LowestPrice", "Entry_Eff", "Exit_Eff", "Trade_Eff"); //save all deals for(int i=0; i<m_virtual_deals_total; i++) { FileWrite(filehandle, m_deals_history[i].symbol, m_deals_history[i].direction, m_deals_history[i].profit, m_deals_history[i].volume, m_deals_history[i].time_open, m_deals_history[i].time_close, m_deals_history[i].price_open, m_deals_history[i].price_close, m_deals_history[i].price_highest, m_deals_history[i].price_lowest, m_deals_history[i].entry_eff, m_deals_history[i].exit_eff, m_deals_history[i].trade_eff); } FileClose(filehandle); } //+------------------------------------------------------------------+ //|Function of checking if a new bar has appeared | //+------------------------------------------------------------------+ bool IsNewBar() { static datetime old_time; datetime new_time[1]; int copied=CopyTime(_Symbol,_Period,0,1,new_time); if(copied>0) { if(old_time!=new_time[0]) { old_time=new_time[0]; return(true); } } else { Alert("Error of copying the time, error number =",GetLastError()); ResetLastError(); } return(false); } //+------------------------------------------------------------------+