Организация бесперебойной торговли в терминале МТ5

29 апреля 2015, 18:35
Mikhail Filimonov
0
333

Организация бесперебойной торговли в терминале МТ5

Михаил | 25 февраля, 2015 | Вложения (1)

В статье рассматривается организация бесперебойной торговли в случае отключения электричества или интернета, а так же удалённое управление процессом торговли.

Введение

Коль скоро Вы решили использовать в торговле экспертов и советников,

чтобы ограничить своё времяпровождение за компьютером, то, вероятно,

необходимо позаботится и о том, чтобы советники нормально работали и

в аварийных ситуациях, таких как отключение электроэнергии и интернета.

А также необходимо получить удалённый доступ к компьютеру

из любого места, где есть интернет.

Итак...  


Электропитание

Всем известно об источниках бесперебойного питания (ИП).

Но как же правильно выбрать его?

Самым главным параметром для ИП является скорость

переключения из штатного режима в аварийный.

И очень желательно, чтобы ИП имел USB связь с Вашим компьютером,

тогда Вы сможете составлять сценарии работы и выключения компьютера

в аварийном режиме (отключение электричества).

 

Следует также уделить внимание блоку питания (БП) Вашего

компьютера. Мощность потребления складывается и мощности потребления всех

компонентов, входящих в состав ПК, плюс запас в 20-30%.

Не следует покупать БП в два-три раза превышающий суммарную

мощность потребления ПК.

Но не только мощностью потребления характеризуются БП,

но и качеством. Наивысшим качеством исполнения

обладают БП c сертификатом 80 Plus Platinum

 

Это совсем не значит, что Вы должны купить именно такой,

но лучше приобрести БП с сертификатом (они гораздо надёжнее). 


Интернет соединения

Вот тут и начинаются проблемы, которые и побудили меня написать эту статью.

Казалось чего проще?

 

Взял двух независимых провайдеров, подключил провода к компьютеру (или к маршрутизатору ), расставил метрики адаптеров и...

Но не тут-то было!

А не переключаются автоматически адаптеры ни в Windows, ни в маршрутизаторах, если кабель физически подключен и есть напряжение

на общем маршрутизаторе провайдера в вашем доме. А самое главное, сам Терминал МТ5 должен сообщить нам о потере связи.

Важно отметить, что ADSL соединение не зависит от электричества, и если у Вас в городе есть провайдер, который

предоставляет услуги интернета по телефонной линии, то очень рекомендую воспользоваться им в качестве резервного канала интернета.

Если нет, то можно воспользоваться "воздушными" соединениями сотовых операторов (значительно дороже),

но ОБЯЗАТЕЛЬНО резервное соединение никак не должно быть связано с поставщиком основного

канала интернета. 

Приведённый ниже код библиотеки ( DLL ) написан в Delphi XE4.

Эта DLL позволяет осуществлять проверку состояния сетевых адаптеров в Вашей системе, а

также отключать и включать их.

ВАЖНО! Для нормальной работы библиотеки Терминал МТ5 необходимо запускать

от имени администратора. 

//+------------------------------------------------------------------+
//|                                                    netswitch.dll |
//|                                          Copyright 2015, Mikalas |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
library netswitch;

uses
  Winapi.Windows, System.SysUtils, Winapi.ActiveX, System.Win.ComObj,
  Winapi.UrlMon, System.Variants;

const
  wbemFlagForwardOnly = $00000020;
//---Коды возврата инициализации DLL
  INIT_DLL_FAILED         = -1;
  INIT_DLL_SUCCES         = 0;
  INIT_DLL_WRONG_NAME_ONE = 1;
  INIT_DLL_WRONG_NAME_TWO = 2;
//---Коды возврата состояния адаптеров
  STATE_UNKNOWN             = -1;
  STATE_MAIN_SLAVE_DISABLED = 0;
  STATE_MAIN_SLAVE_ENABLED  = 1;
  STATE_MAIN_ENABLED        = 2;
  STATE_SLAVE_ENABLED       = 3;

var
  MainName, SlaveName: string;

function GetAdapter( aName: string; ip_enabled: boolean ): boolean;
var
  oBindObj: IDispatch;
  oNetAdapters, oNetAdapter,
  odnsAddr, oWMIService: OleVariant;
  i, iValue: longword;
  oEnum: IEnumvariant;
  oCtx: IBindCtx;
  oMk: IMoniker;
  sFileObj: WideString;
  a_str: string;
  k: integer;
begin
  Result:= false;
//---Инициализация ActiveX
  CoInitialize( nil );
  try
    sFileObj:= 'winmgmts:\\.\root\cimv2';
//---
    OleCheck( CreateBindCtx( 0, oCtx ) );
    OleCheck( MkParseDisplayNameEx( oCtx,PWideChar( sFileObj ), i, oMk ) );
    OleCheck( oMk.BindToObject( oCtx,nil, IUnknown, oBindObj ) );
    oWMIService:= oBindObj;
    if ( ip_enabled ) then
      oNetAdapters:= oWMIService.ExecQuery( 'Select * from ' +
    'Win32_NetworkAdapterConfiguration ' +
    'where IPEnabled=TRUE') else
    oNetAdapters:= oWMIService.ExecQuery( 'Select * from ' +
    'Win32_NetworkAdapterConfiguration ' +
    'where IPEnabled=FALSE');
    oEnum:= IUnknown( oNetAdapters._NewEnum ) as IEnumVariant;
  //---
    while ( oEnum.Next( 1, oNetAdapter, iValue ) = 0 ) do
    begin
      try
        a_str:= oNetAdapter.Caption;
        k:= Pos( ']', a_str );
        if ( k > 0 ) then
        begin
           Delete( a_str, 1, k + 1) ;
          if ( aName = a_str ) then
          begin
            Result:= true;
            oNetAdapter:= Unassigned;
            break;
          end;
        end;
      except
      end;
      oNetAdapter:= Unassigned;
    end;
//---
    odnsAddr:= Unassigned;
    oNetAdapters:= Unassigned;
    oWMIService:= Unassigned;
  finally
    CoInitialize( Nil );
  end;
end;

function InitNetSwitch( main_name: PAnsiString; slave_name: PAnsiString ): Integer;  stdcall;
var
  is_main_found: boolean;
  is_slave_found: boolean;
begin
  Result:= INIT_DLL_FAILED;
  is_main_found:= false;
  is_slave_found:= false;
//---
  MainName:= string( main_name );
  SlaveName:= string( slave_name );
//---Проверка существования основного адаптера с указанным описанием
  if ( MainName <> '' ) then
    if ( GetAdapter( MainName, false ) ) then is_main_found:= true else
      if ( GetAdapter( MainName, true ) ) then is_main_found:= true;
//---Проверка существования запасного адаптера с указанным описанием
  if ( SlaveName <> '' ) then
    if ( GetAdapter( SlaveName, false ) ) then is_slave_found:= true else
      if ( GetAdapter( SlaveName, true ) ) then is_slave_found:= true;
//---Результаты проверки
  if ( is_main_found and is_slave_found ) then Result:= INIT_DLL_SUCCES else
    if ( is_main_found and ( not is_slave_found ) ) then Result:= INIT_DLL_WRONG_NAME_TWO else
      if ( ( not is_main_found ) and is_slave_found ) then Result:= INIT_DLL_WRONG_NAME_ONE;
end;


function GetAdaptersState(): Integer; stdcall;
begin
  Result:= STATE_UNKNOWN;
//---Проверка состояния адаптеров
  if ( ( MainName <> '' ) and ( SlaveName <> '' ) ) then
  begin
    if ( GetAdapter( MainName, true ) ) then
    begin
      if ( GetAdapter( SlaveName, true ) ) then Result:= STATE_MAIN_SLAVE_ENABLED else
        Result:= STATE_MAIN_ENABLED;
    end else
    begin
      if ( GetAdapter( SlaveName, true ) ) then Result:= STATE_SLAVE_ENABLED else
        Result:= STATE_MAIN_SLAVE_DISABLED;
    end;
  end;
end;

function EnableDisableAdapter( a_name: string; disable_enable: boolean ): boolean;
var
 FSWbemLocator: OLEVariant;
 FWMIService: OLEVariant;
 FWbemObjectSet: OLEVariant;
 FWbemObject: OLEVariant;
 oEnum: IEnumvariant;
 iValue: LongWord;
 a_str: string;
 k: integer;
begin
  Result:= false;
//---Инициализация ActiveX
  CoInitialize( nil );
  try
    if ( a_name <> '' ) then
    begin
      FSWbemLocator:= CreateOleObject( 'WbemScripting.SWbemLocator' );
      FWMIService:= FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '' );
      if ( disable_enable ) then
        FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapter Where NetEnabled=False',
                                                     'WQL', wbemFlagForwardOnly ) else
      FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_NetworkAdapter Where NetEnabled=True',
                                                     'WQL', wbemFlagForwardOnly );
      oEnum:= IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
      while oEnum.Next(1, FWbemObject, iValue ) = 0 do
      begin
        a_str:= FWbemObject.Caption;
        k:= Pos( ']', a_str );
        if ( k > 0 ) then
        begin
          Delete( a_str, 1, k + 1 );
          if ( a_name = a_str ) then
          begin
            if ( disable_enable ) then
              FWbemObject.Enable() else
            FWbemObject.Disable();
            Result:= true;
          end;
        end;
        FWbemObject:= Unassigned;
      end;
    end;
  finally
    CoInitialize( nil );
  end;
end;

function DisableMain(): Boolean; stdcall;
begin
  Result:= EnableDisableAdapter( MainName, false );
end;

function EnableMain(): Boolean; stdcall;
begin
  Result:= EnableDisableAdapter( MainName, true );
end;

function DisableSlave(): Boolean; stdcall;
begin
  Result:= EnableDisableAdapter( SlaveName, false );
end;

function EnableSlave(): Boolean; stdcall;
begin
  Result:= EnableDisableAdapter( SlaveName, true );
end;

exports
  InitNetSwitch,
  GetAdaptersState,
  DisableMain,
  EnableMain,
  DisableSlave,
  EnableSlave;

begin

end.

 

Библиотека должна находится в папке

C:\Users\ИМЯ_ПОЛЬЗОВАТЕЛЯ\AppData\Roaming\MetaQuotes\Terminal\НОМЕР_ТЕРМИНАЛА\MQL5\Libraries  

 

Теперь рассмотрим как работает эксперт Net_switcher:

 

//+------------------------------------------------------------------+
//|                                                 Net_switcher.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Mikalas"
#property link      "http://www.mql5.com"
#property version   "1.00"
//
enum ENUM_INIT_DLL
{
  INIT_DLL_FAILED           = -1,
  INIT_DLL_SUCCES           = 0,
  INIT_DLL_WRONG_NAME_ONE   = 1,
  INIT_DLL_WRONG_NAME_TWO   = 2
};
enum ENUM_NET_STATE
{
  STATE_UNKNOWN             = -1,
  STATE_MAIN_SLAVE_DISABLED = 0,
  STATE_MAIN_SLAVE_ENABLED  = 1,
  STATE_MAIN_ENABLED        = 2,
  STATE_SLAVE_ENABLED       = 3
};
//
#import "netswitch.dll"
ENUM_INIT_DLL InitNetSwitch( const string NameOne, const string NameTwo );
ENUM_NET_STATE GetAdaptersState();
bool DisableMain();
bool EnableMain();
bool DisableSlave();
bool EnableSlave();
#import
//
input string	       p_expert     = "=== Параметры эксперта ===";                 //  
input uint            TimerTime    = 500;                                          //Период таймера (мсек)
input string          AdaptNameOne = "Intel(R) 82579V Gigabit Network Connection"; //Описание основного адаптера
input string          AdaptNameTwo = "Realtek PCIe GBE Family Controller";         //Описание запасного адаптера
input string          p_chart      = "=== Параметры графика ===";	                 //  
input color           ButtDown     = clrMagenta;                                   //Цвет нажатой кнопки
input color           ButtUp       = clrMediumSeaGreen;                            //Цвет отжатой кнопки
input uint            FontSize     = 10;                                           //Размер фонта
input uint            StrSpace     = 13;                                           //Расстояние между строками
input color           FontColor    = clrWhite;                                     //Цвет фонта
input ENUM_CHART_MODE Chart_mode   = CHART_CANDLES;                                //Режим графика
input ENUM_TIMEFRAMES TimeFrame    = PERIOD_CURRENT;                               //Период графика
input color           Candle_bull  = clrGreen;                                     //Цвет Бычьей свечи
input color           Candle_bear  = clrRed;                                       //Цвет Медвежьей свечи
input color           BackGround   = clrGray;                                      //Цвет фона 
input color           Color_last   = clrWhite;                                     //Цвет последней цены
input color           Chart_up     = clrBlack;                                     //Цвет свечи вверх
input color           Chart_down   = clrBlack;                                     //Цвет свечи вниз
input color           Chart_grid   = clrDarkGray;                                  //Цвет сетки
//
bool           h_res;
bool           not_first;
bool           is_connected;
MqlDateTime    tick_time;
ENUM_NET_STATE net_state;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  not_first = false;
  
//---Инициализация DLL
  ENUM_INIT_DLL init_dll = InitNetSwitch( AdaptNameOne, AdaptNameTwo );
  
  switch( init_dll )
  {
    case INIT_DLL_FAILED: MessageBox( "Ошибка инициализации netswitch.dll!", "Ошибка", MB_OK | MB_ICONHAND );
                          return( INIT_FAILED );
                          break;
                          
    case INIT_DLL_WRONG_NAME_ONE: MessageBox( "Не найден сетевой адаптер с описанием " +
                                              AdaptNameOne + " .", "Ошибка", MB_OK | MB_ICONHAND );
                                  return( INIT_FAILED );
                                  break;
                                  
    case INIT_DLL_WRONG_NAME_TWO: MessageBox( "Не найден сетевой адаптер с описанием " +
                                              AdaptNameTwo + " .", "Ошибка", MB_OK | MB_ICONHAND );
                                  return( INIT_FAILED );
                                  break;                                                    
  }
//--- Проверка состояния сетевых адаптеров
  net_state = GetAdaptersState();
//---  
  switch( net_state )
  {
    case STATE_UNKNOWN:             MessageBox( "Ошибка проверки адаптеров!", "Ошибка", MB_OK | MB_ICONHAND );
                                    return( INIT_FAILED ); 
                                    break; 
                                    
    case STATE_MAIN_SLAVE_DISABLED: h_res = EnableMain(); //Подключаем адаптеры. Первым - основной
                                    if ( h_res )
                                    {
                                      EnableSlave();
                                    } 
                                    break; 
                                    
    case STATE_MAIN_ENABLED:        EnableSlave(); //Подключаем запасной адаптер
                                    break; 
                                    
    case STATE_SLAVE_ENABLED:       h_res = DisableSlave(); //Отключаем запасной, включаем основной, а затем, опять включаем запасной
                                    if ( h_res )
                                    {
                                      h_res = EnableMain();
                                      if ( h_res )
                                      {
                                        EnableSlave();
                                      }
                                    }
                                    break;
                                    
    case STATE_MAIN_SLAVE_ENABLED:  h_res = DisableSlave(); //Так как мы не знаем какой адаптер используется, мы делаем рабочим основной адаптер
                                    if ( h_res )
                                    {
                                      EnableSlave();
                                    }
                                    break;                                                                                                 
  } 
//---
  //---
  if( !ObjectCreate( 0, "reset_button", OBJ_BUTTON, 0, 0, 0 ) )
  {
    MessageBox( "Кнопка 'Reset' не создана!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
  else
  {
    ObjectSetInteger( 0, "reset_button", OBJPROP_CORNER, CORNER_RIGHT_LOWER );
    ObjectSetInteger( 0, "reset_button", OBJPROP_XDISTANCE, 40 );             
    ObjectSetInteger( 0, "reset_button", OBJPROP_YDISTANCE, 18 );
    ObjectSetInteger( 0, "reset_button", OBJPROP_XSIZE, 40 );
    ObjectSetInteger( 0, "reset_button", OBJPROP_YSIZE, 18 );
    ObjectSetInteger( 0, "reset_button", OBJPROP_BGCOLOR, ButtUp );
    ObjectSetInteger( 0, "reset_button", OBJPROP_STATE, false );
    ObjectSetString( 0, "reset_button", OBJPROP_TEXT, "Reset" );
  }
//---инфострока
  if( !ObjectCreate( 0, "info_label_1", OBJ_LABEL, 0, 0, 0 ) )
  {
    MessageBox( "Инфострока 1 не создана!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
  else
  {
    ObjectSetInteger( 0, "info_label_1", OBJPROP_CORNER, CORNER_LEFT_UPPER );
    ObjectSetInteger( 0, "info_label_1", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER );
    ObjectSetInteger( 0, "info_label_1", OBJPROP_XDISTANCE, 5 );             
    ObjectSetInteger( 0, "info_label_1", OBJPROP_YDISTANCE, 15 );
    ObjectSetInteger( 0, "info_label_1", OBJPROP_FONTSIZE, FontSize );
    ObjectSetInteger( 0, "info_label_1", OBJPROP_COLOR, FontColor );
    ObjectSetInteger( 0, "info_label_1",OBJPROP_BACK, false );
    ObjectSetString( 0, "info_label_1", OBJPROP_TEXT, "Инициализация..." );
  }  
//--- Set chart in candles    
  if ( !ChartSetInteger(0, CHART_MODE, Chart_mode ) ) 
  {
    MessageBox( "Режим свечей не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Set Time Frame H1
  if ( !ChartSetSymbolPeriod( 0, NULL, TimeFrame ) )
  {
    MessageBox( "Период графика не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Set candles color
  if ( !ChartSetInteger( 0, CHART_COLOR_CANDLE_BULL, Candle_bull ) )
  {
    MessageBox( "Цвет бычьих свечей не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//---      
  if ( !ChartSetInteger( 0, CHART_COLOR_CANDLE_BEAR, Candle_bear ) )
  {
    MessageBox( "Цвет медвежьих свечей не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  } 
//--- Set fon color
  if ( !ChartSetInteger( 0, CHART_COLOR_BACKGROUND, BackGround ) )
  {
    MessageBox( "Цвет фона не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Set hide line bid
  if ( !ChartSetInteger( 0, CHART_SHOW_BID_LINE, false ) )
  {
    MessageBox( "Не скрыта линия BID!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }   
//--- Set show line last 
  if ( !ChartSetInteger(0, CHART_SHOW_LAST_LINE, true ) )
  {
    MessageBox( "Линия последней цены не установлена!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }      
//--- Set line bid color
  if ( !ChartSetInteger(0, CHART_COLOR_LAST, Color_last ) )
  {
    MessageBox( "Цвет линии последней цены не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Set color bid up
  if ( !ChartSetInteger( 0, CHART_COLOR_CHART_UP, Chart_up ) )
  {
    MessageBox( "Цвет свечи вверх не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Set color bid up
  if ( !ChartSetInteger( 0, CHART_COLOR_CHART_DOWN, Chart_down ) )
  {
    MessageBox( "Цвет свечи вниз не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }
//--- Color grid
  if ( !ChartSetInteger( 0, CHART_COLOR_GRID, Chart_grid ) )
  {
    MessageBox( "Не установлен цвет сетки!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }    

//---Проверка подключения терминала к торговому серверу
  if ( TerminalInfoInteger( TERMINAL_CONNECTED ) )
  {
    is_connected = true;
  }
  else
  {
    is_connected = false;
  }
  ObjectSetString( 0, "info_label_1", OBJPROP_TEXT, "Соединение через основной адаптер." );
  ChartRedraw();
//--- Установка таймера
  if ( !EventSetMillisecondTimer( TimerTime ) )
  {
    MessageBox( "Таймер не установлен!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  }  
  return( INIT_SUCCEEDED );
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit( const int reason )
{
//--- удаление таймера
  EventKillTimer();
//---
  ObjectDelete( 0, "reset_button" ); 
  ObjectDelete( 0, "info_label_1" );
}
//+------------------------------------------------------------------+
//| Expert Switch To Main adapter function                           |
//+------------------------------------------------------------------+
void SwitchToMain( const ENUM_NET_STATE a_state )
{
  switch( a_state )
  {
      case STATE_UNKNOWN:              
      case STATE_MAIN_SLAVE_DISABLED: h_res = EnableMain();
                                      if ( h_res )
                                      {
                                        EnableSlave();
                                      }
                                      break;
                                        
      case STATE_MAIN_SLAVE_ENABLED:  h_res = DisableSlave();
                                      if ( h_res )
                                      {
                                        EnableSlave();
                                      }
                                      break;
                                        
      case STATE_MAIN_ENABLED:        EnableSlave();
                                      break;
                                        
      case STATE_SLAVE_ENABLED:       h_res = DisableSlave();
                                      if ( h_res )
                                      {
                                        h_res = EnableMain();
                                        if ( h_res )
                                        {
                                          EnableSlave();
                                        }
                                      }
                                      break;
  }  
}
//+------------------------------------------------------------------+
//| Expert timer function                                            |
//+------------------------------------------------------------------+
void OnTimer()
{
  TimeTradeServer( tick_time );
//---  
  if ( !TerminalInfoInteger( TERMINAL_CONNECTED ) )
  {
    if ( !not_first )
    {
      not_first = true;
      is_connected = false;
      Print( "OnTimer: Соединение потеряно!" );
      SendMail( "Lost connection", "Соединение потеряно " + string( tick_time.hour ) +
                ":" + string( tick_time.min ) + ":" + string( tick_time.sec ) );
//---
      net_state = GetAdaptersState();
//---      
      switch( net_state )     //Влючаем резервный канал
      {
        case STATE_UNKNOWN:              
        case STATE_MAIN_SLAVE_DISABLED: h_res = EnableSlave();
                                        if ( h_res )
                                        {
                                          EnableMain();
                                        }
                                        break;
                                        
        case STATE_MAIN_SLAVE_ENABLED:  h_res = DisableMain();
                                        if ( h_res )
                                        {
                                          EnableMain();
                                        }
                                        break;
                                        
        case STATE_MAIN_ENABLED:        h_res = DisableMain();
                                        if ( h_res )
                                        {
                                          h_res = EnableSlave();
                                          if ( h_res )
                                          {
                                            EnableMain();
                                          }
                                        }
                                        break;
                                        
        case STATE_SLAVE_ENABLED:       EnableMain();
                                        break;                                
      }          
    }
  }
  else
  {                        //Соединение восстановлено
    if ( !is_connected )
    {
      not_first = false;
      is_connected = true;
      Print( "OnTimer: Соединение восстановлено!" );
      ObjectSetString( 0, "info_label_1", OBJPROP_TEXT, "Соединение через запасной адаптер." );
      ChartRedraw();                 
    }
  }  
}
//+------------------------------------------------------------------+
//| Expert Chart event function                                      |
//+------------------------------------------------------------------+
void OnChartEvent( const int id, const long& lparam, const double& dparam, const string& sparam )
{
  long b_state;
  
  if ( id == CHARTEVENT_OBJECT_CLICK )
  {
    if ( sparam == "reset_button" )
    {
      if ( ObjectGetInteger( 0, "reset_button", OBJPROP_STATE, 0, b_state ) )
      {
        if ( b_state == 1 )
        {
          ObjectSetInteger( 0, "reset_button", OBJPROP_BGCOLOR, ButtDown );
          ObjectSetString( 0, "reset_button", OBJPROP_TEXT, "Reset" );
          ChartRedraw();
//---     
          net_state = GetAdaptersState();
          SwitchToMain( net_state );  
          ObjectSetString( 0, "info_label_1", OBJPROP_TEXT, "Соединение через основной адаптер." );   
          ObjectSetInteger( 0, "reset_button", OBJPROP_STATE, false ); 
          ObjectSetInteger( 0, "reset_button", OBJPROP_BGCOLOR, ButtUp );
          ObjectSetString( 0, "reset_button", OBJPROP_TEXT, "Reset" );
          ChartRedraw();     
        }
      }
    }
  }
}    
//+------------------------------------------------------------------+
//| The END                                                          |
//+------------------------------------------------------------------+

 

 Библиотека использует описания (не имена в Windows) сетевых адаптеров ( см. рис)

 

 

 которые необходимо ввести в настройках эксперта, другие настройки интуитивно понятны.

 При инициализации эксперта, выключая и выключая адаптеры (мы не знаем через который установлено

соединение), эксперт устанавливает соединение через основной (1 в настройках эксперта) адаптер.

 

Далее запускается таймер, который с периодом 0,5 сек. проверяет состояние сети. 

Логика проверки несложная. 

При отсутствии соединения эксперт переключает соединение на запасной адаптер.

Нет смысла автоматически пытаться (потом) переключится на основной адаптер, так как

мы не знаем причины разрыва соединения ("упал" торговый сервер или нет интернета).

 Кнопка "Reset" позволяет установить эксперта в исходное состояние (работа через основной адаптер).

 

Эксперт, при потере соединения, может отсылать e-mail на

указанный в настройках терминала адрес.

 

На www.mail.ru можно настроить почтовый ящик таким образом, чтобы в папку

"Входящие" помещались письма "от самого себя", а все остальные помещаются в

папку "СПАМ". Также, можно настроить отправку СМС, при появлении в папке

"Входящие" нового письма. Рекомендую придумать "навороченное" имя

н-р: jsdg!lzsnfdh486skldjg9824@mail.ru, чтобы имя ящика было как можно

более уникальным. Тогда Вы точно будете получать письма и СМС только от терминала.

  

Удалённое управление

В качестве инструмента удалённого управления успешно использую TeamViewer

(для личного пользования - бесплатный). 

 

http://www.teamviewer.com/ru/index.aspx

Преимущество  TeamViewer:

1. Не "привязан" к IP адресу компьютера

2. При его использовании происходит двойная проверка доступа к ПК.

( сам TeamViewer требует ID, пароль и пароль на Вашем ПК ) 

3. Суперпростой. 

Заключение

Предпринятые меры по организации бесперебойной торговли позволят Вам

с невысокой долей беспокойства за процесс торговли отлучаться на недельку из дома ( н-р на рыбалку :)  )

Надеюсь, что статья будет полезна не только начинающим трейдерам.

С уважением, и удачной торговли!

P/S Исходные и откомпилированные файлы в ZIP-архиве,

предоставляются для личного пользования. 

 

Файлы:
Поделитесь с друзьями: