程序库: 虚拟 - 页 4

 
<br/ translate="no">

fxsaber、

感谢您的快速回复。

您的建议解决了交易总数不一致的问题,我试着在代码顶部使用定义 VIRTUAL_CLOSEALL_BYEND 调用 Stop()。

我还添加了 IsNewBar 测试,以减少交易次数。


// 在真实和虚拟交易环境中启动 TS

//需要允许测试人员作为真实策略进行交易
#include <MT4Orders.mqh>               // https://www.mql5.com/ru/code/16006
#define  VIRTUAL_TESTER                 // 在虚拟交易环境中启动
#define  VIRTUAL_CLOSEALL_BYEND
#include <fxsaber\Virtual\Virtual.mqh> // 虚拟交易环境


input double Lots  = 1;
input int Interval = 100;  // 位置寿命
input bool Example = true; // 选择哪个示例代码

datetime bartime;

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool och_NewBar(string _symbol, ENUM_TIMEFRAMES _timeframe, datetime& _lasttime)
{

if(::iTime(_symbol,_timeframe,0) != _lasttime)
  {
   _lasttime=::iTime(_symbol,_timeframe,0);
   return (true);
  }
else
   return (false);
}

// 可逆 TC
void System()
{
  
  if (!OrderSelect(OrdersTotal() - 1, SELECT_BY_POS))
    OrderSend(_Symbol, OP_BUY, Lots, SymbolInfoDouble(_Symbol, SYMBOL_ASK), 100, 0, 0); // 如果没有位置 - 打开
  else if (TimeCurrent() - OrderOpenTime() > Interval) // 如果位置的生存时间超过指定时间
  {
    // 翻转位置
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100);
    OrderSend(_Symbol, 1 - OrderType(), Lots, OrderClosePrice(), 100, 0, 0);
  }
  //PrintFormat("%s-Line#%d::HistoryOrders.Total() = %d",__FUNCTION__,__LINE__,OrdersHistoryTotal());
}

int handle = VIRTUAL::Create(); // 创建虚拟交易环境的句柄。0 - 真实交易环境

void OnTick()
{
  //static const int handle = VIRTUAL::Create(); // 为虚拟交易环境创建一个句柄。0 - 真实交易环境

  if (!och_NewBar(_Symbol, _Period, bartime)) return;
  
  if (Example)
  {
    if (VIRTUAL::SelectByHandle()) // 选择真实的交易环境
      System();                    // 在选定的交易环境(真实)上启动 TS

    if (VIRTUAL::SelectByHandle(handle)) // 选择虚拟交易环境
    {
      VIRTUAL::NewTick();      // 为虚拟交易环境添加了一个刻度线
      System();                // 在选定的交易环境(虚拟)上启动 TS
    }
  }
  else // 同样动作的另一种记录。
    // 查看所有可用的交易环境
    for (int i = 0; i <= VIRTUAL::Total(); i++)
      if (VIRTUAL::SelectByIndex(i)) // 选择合适的交易环境
      {
        VIRTUAL::NewTick(); // 为选定的交易环境添加一个刻度线

        System(); // 在选定的交易环境中启动 TS
      }

  Comment(VIRTUAL::ToString()); // 在图表中显示虚拟交易环境的状况
}

void OnDeinit(const int reason)
{
  VIRTUAL::SelectByHandle();
  PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Real", 0,AccountBalance(), AccountEquity(), AccountProfit(), OrdersHistoryTotal());
  VIRTUAL::SelectByHandle(handle);
  VIRTUAL::Stop();
  PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Virtual", 0,AccountBalance(), AccountEquity(), AccountProfit(), OrdersHistoryTotal());
                                                                        
  Comment("");
}


但我认为余额应该是(初始存款 - 利润),利润应该是(初始存款 - 交易损失 + 交易利润),正如我们在真实 TS 的回溯测试结果中看到的那样。

因此,余额是正确的,但利润不能是 Orders.mqh 中定义的(余额 - 净值)。

 double AccountProfit( void ) const
  {
    return(::NormalizeDouble(this.Equity - this.Balance, 2));
  }

我也不明白为什么实际 TS 的 AccountInfoDouble(ACCOUNT_PROFIT) 返回值为 0。

  static double VirtualAccountProfit( void )
  {
    return(VIRTUAL::SelectOrders ? VIRTUAL::SelectOrders.AccountProfit() : ::AccountInfoDouble(ACCOUNT_PROFIT));
  }

我说错了吗?




 
och:

fxsaber、

感谢您的快速回复。

您的建议解决了交易总数不一致的问题,我尝试在代码顶部使用定义 VIRTUAL_CLOSEALL_BYEND 调用 Stop()。

我还添加了 IsNewBar 测试,以减少交易次数。



但我认为余额应该是(初始存款 - 利润),利润应该是(初始存款 - 交易损失 + 交易利润),正如我们在真实 TS 的回溯测试结果中看到的那样。

因此,余额是正确的,但利润不能是 Orders.mqh 中定义的(余额 - 净值

我也不明白为什么实际 TS 的 AccountInfoDouble(ACCOUNT_PROFIT) 返回值为 0。

我说错了吗?





因此,这不是一个很好的解决问题的方法,还需要对虚拟 TS 进行调查:

void OnDeinit(const int reason)
{
  //--- 计算 TS 的实际数字
  VIRTUAL::SelectByHandle();
  OrderSelect(1, SELECT_BY_TICKET, MODE_HISTORY);
  double deposit = OrderProfit();
  double profit = AccountBalance() - deposit;
  PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Real", deposit,AccountBalance(), AccountEquity(), profit, OrdersHistoryTotal());
  
  //--- 计算虚拟 TS 数字
  VIRTUAL::SelectByHandle(handle);
  VIRTUAL::Stop();
  OrderSelect(1, SELECT_BY_TICKET, MODE_HISTORY);
  deposit = OrderProfit();
  profit = AccountBalance() - deposit;
  PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Virtual", deposit,AccountBalance(), AccountEquity(), profit, OrdersHistoryTotal());
                                                                        
  Comment("");
}
  
 
och:

但我认为,余额应该是(初始存款 - 利润),利润应该是(初始存款 - 交易损失 + 交易利润),正如我们可以在真实 TS 的回溯测试结果中看到的那样。

因此,余额是正确的,但利润不能是 Orders.mqh 中定义的(余额 - 净值

我也不明白为什么实际 TS 的 AccountInfoDouble(ACCOUNT_PROFIT) 返回值为 0。

我说错了吗?

ACCOUNT_PROFIT 等于当前所有未结头寸的利润总和。

 
och:

因此,这并不是一个很好的解决问题的方法,还需要对虚拟 TS 进行调查:

  double deposit = TesterStatistics(STAT_INITIAL_DEPOSIT);
  double profit = TesterStatistics(STAT_PROFIT);
 

fxsaber、

再次感谢您的支持和反应。

我又更新了一下代码,并尝试将 TS 环境的使用分开。

我了解了使用真实或虚拟环境时的结果。结果符合预期。

我不明白同时使用两种环境时的结果。

能否以 CSV 文件形式提取订单列表?

谨致问候、

och

// 在真实和虚拟交易环境中启动 TS

//需要允许测试人员作为真实策略进行交易
#include <MT4Orders.mqh>               // https://www.mql5.com/ru/code/16006
#define  VIRTUAL_TESTER                 // 在虚拟交易环境中启动
//#define VIRTUAL_CLOSEALL_BYEND
#include <fxsaber\Virtual\Virtual.mqh> // 虚拟交易环境

enum ENUM_TRADING_TYPE{
   TRADING_TYPE_REAL,         // 使用真实环境
   TRADING_TYPE_VIRTUAL,      // 使用虚拟环境
   TRADING_TYPE_BOTH          // 同时使用
};

input double               Lots  = 1;
input int                  Interval = 100;                     // 位置寿命
//input bool Example = true;// 选择哪个示例代码
input ENUM_TRADING_TYPE    Trading_type = TRADING_TYPE_REAL;   //测量类型

datetime bartime;

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool och_NewBar(string _symbol, ENUM_TIMEFRAMES _timeframe, datetime& _lasttime)
{

if(::iTime(_symbol,_timeframe,0) != _lasttime)
  {
   _lasttime=::iTime(_symbol,_timeframe,0);
   return (true);
  }
else
   return (false);
}

// 可逆 TC
void System()
{
  
  if (!OrderSelect(OrdersTotal() - 1, SELECT_BY_POS))
    OrderSend(_Symbol, OP_BUY, Lots, SymbolInfoDouble(_Symbol, SYMBOL_ASK), 100, 0, 0); // 如果没有位置 - 打开
  else if (TimeCurrent() - OrderOpenTime() > Interval) // 如果位置停留时间超过指定时间
  {
    // 翻转位置
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100);
    OrderSend(_Symbol, 1 - OrderType(), Lots, OrderClosePrice(), 100, 0, 0);
  }
  //PrintFormat("%s-Line#%d::HistoryOrders.Total() = %d",__FUNCTION__,__LINE__,OrdersHistoryTotal());
}

int handle = VIRTUAL::Create(); // 创建虚拟交易环境的句柄。0 - 真实交易环境

void OnTick()
{
  //static const int handle = VIRTUAL::Create(); // 为虚拟交易环境创建一个句柄。0 - 真实交易环境

  if (!och_NewBar(_Symbol, _Period, bartime)) return;
  
  //如果(示例)
  {
    switch(Trading_type){
      case TRADING_TYPE_REAL     :    if (VIRTUAL::SelectByHandle())       // 选择真实的交易环境
                                          System();                        // 在选定的交易环境(真实)上启动 TS
                                      break;
                                        
      case TRADING_TYPE_VIRTUAL  :    if (VIRTUAL::SelectByHandle(handle)) // 选择虚拟交易环境
                                        {
                                          VIRTUAL::NewTick();              // 为虚拟交易环境添加了一个刻度线
                                          System();                        // 在选定的交易环境(虚拟)上启动 TS
                                        }
                                      break;
                                      
      case TRADING_TYPE_BOTH     :    if (VIRTUAL::SelectByHandle())       // 选择真实的交易环境
                                          System();                        // 在选定的交易环境(真实)上启动 TS
                                      break;
                                        
                                      if (VIRTUAL::SelectByHandle(handle)) // 选择虚拟交易环境
                                        {
                                          VIRTUAL::NewTick();              // 为虚拟交易环境添加了一个刻度线
                                          System();                        // 在选定的交易环境(虚拟)上启动 TS
                                        }
                                      break;
    }
  }
// else // 相同操作的另一种记录。
// // 查看所有可用的交易环境
// for (int i = 0; i <= VIRTUAL::Total(); i++)
// if (VIRTUAL::SelectByIndex(i))// 选择适当的交易环境
// {
// VIRTUAL::NewTick(); // 为选定的交易环境添加一个刻度线
//
// System(); // 在选定的交易环境中启动 TS
// }

  Comment(VIRTUAL::ToString()); // 在图表中显示虚拟交易环境的状况
}

void OnDeinit(const int reason)
{
  double deposit, profit;
  //--- 计算 TS 的实际数字
  if (Trading_type != TRADING_TYPE_VIRTUAL){
     VIRTUAL::SelectByHandle();
     OrderSelect(1, SELECT_BY_TICKET, MODE_HISTORY);
     deposit = TesterStatistics(STAT_INITIAL_DEPOSIT);
     profit = TesterStatistics(STAT_PROFIT);
     PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Real", deposit,AccountBalance(), AccountEquity(), profit, OrdersHistoryTotal());
  }
  
  if (Trading_type != TRADING_TYPE_REAL){
     //--- 计算虚拟 TS 数字
     VIRTUAL::SelectByHandle(handle);
     VIRTUAL::Stop();
     deposit = TesterStatistics(STAT_INITIAL_DEPOSIT);
     profit = TesterStatistics(STAT_PROFIT);
     PrintFormat("(%s-%s)::%s - Initial deposit=%.2f, Balance=%.2f, Equity=%.2f, Profit=%G, Trades=%d", _Symbol, EnumToString(_Period), "Virtual", deposit,AccountBalance(), AccountEquity(), profit, OrdersHistoryTotal());
  }                                                                      
  Comment("");
}
 
och:

我不明白同时使用这两种环境会产生什么结果。

这个库有很多用例。您看到的是一般视图的示例。

是否可以将订单列表提取为 CSV 文件?

在下面的示例中,您可以在输入参数中更改交易环境:真实或虚拟。

#include <MT4Orders.mqh>               // https://www.mql5.com/ru/code/16006

#define  VIRTUAL_TESTER                 // 在虚拟交易环境中启动
#define  VIRTUAL_CLOSEALL_BYEND
#include <fxsaber\Virtual\Virtual.mqh> // 虚拟交易环境

input double                inLots  = 1 ;
input int                   inInterval = 100 ;                     // 位置寿命

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool och_NewBar( string _symbol, ENUM_TIMEFRAMES _timeframe )
{
static datetime _lasttime = 0;

if (:: iTime (_symbol,_timeframe, 0 ) != _lasttime)
  {
   _lasttime=:: iTime (_symbol,_timeframe, 0 );
   return ( true );
  }
else
   return ( false );
}

// 可逆 TC
void System()
{
  
   if (! OrderSelect ( OrdersTotal () - 1 , SELECT_BY_POS))
     OrderSend ( _Symbol , OP_BUY, inLots, SymbolInfoDouble ( _Symbol , SYMBOL_ASK ), 100 , 0 , 0 ); // 如果没有位置 - 打开
   else if ( TimeCurrent () - OrderOpenTime() > inInterval) // 如果位置停留时间超过指定时间
  {
     // 翻转位置
    OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 100 );
     OrderSend ( _Symbol , 1 - OrderType(), inLots, OrderClosePrice(), 100 , 0 , 0 );
  }
   //PrintFormat("%s-Line#%d::HistoryOrders.Total() = %d",__FUNCTION__,__LINE__,OrdersHistoryTotal());
}

void OnTick ()
{
   if (!och_NewBar( _Symbol , _Period)) return ;
   
   System();
}

#define  REPORT_TESTER             // В тестере будут автоматически записываться отчеты
// #define REPORT_INTERACTIVE_CHARTS // Добавляет в отчет интерактивные графики.
#define  REPORT_BROWSER            // Создание отчета с запуском браузера - требует разрешения DLL.
#include <Report.mqh> // https://www.mql5.com/ru/code/ 22577


底部的行创建 HTML 报告。如果启用了 DLL,那么在测试结束后,该报告将自动出现在浏览器中。

 
Automated-Trading :

虚拟

作者: fxsaber

你好,我想知道这个库是否适用于 mt4?

因为当我导入库时,出现了一些编译错误,谢谢。

附加的文件:
 
You Lin Lee:

您好,请问该库是否适用于 mt4?

因为在我导入库时,出现了一些编译错误,谢谢

这是MQL4 的错误!基本主题在这里

 

交易、自动交易系统和交易策略测试论坛

MT5 和作战性能速度

fxsaber, 2021.03.01 12:19 pm.

// Quick SymbolInfoTick.
bool SymbolInfoTickFast( const string &Symb, MqlTick &Tick )
{
  return((Symb == _Symbol) ? SymbolInfoTick(_Symbol, Tick)
                           : SymbolInfoTick(Symb, Tick));
}

在虚拟中实施这一事实能够在真实环境中加快速度。

 

亲爱的 fxsaber、

感谢您的好意。这个工具非常有用。

这个程序有 MT4 版本吗?