Practice

Рекомендации по практике использования библиотеки ATcl

Последнюю версию библиотеки всегда можно скачать следуя инструкциям на странице install

Узнать какая версия библиотеки ATcl и языка Tcl можно простым скриптом:

#include <ATcl\\ATcl.mqh>
 
void OnStart()
{
  PrintFormat("ATcl version: %s",ATcl_Version());
  ATcl_OnInit();
  ATcl *tcl=new ATcl;
  if (tcl!=NULL && tcl.Ready()) {
    PrintFormat("Tcl version: %f",tcl.DoubleEval("info tclversion"));
    PrintFormat("Tcl pathLevel: %s",tcl.StringEval("set tcl_patchLevel"));
    PrintFormat("Tcl library: %s",tcl.StringEval("info library"));
    PrintFormat("    auto_path: %s",tcl.StringEval("set auto_path"));
    Tcl_Obj names=tcl.Ref(tcl.ObjEval("array names tcl_platform"));
    Tcl_Obj tcl_platform=tcl.Ref(tcl.Obj("tcl_platform"));
    int total=tcl.Count(names);
    for(int t=0;t<total;t++) {
      Tcl_Obj key=tcl.ObjIndex(names,t);
      PrintFormat("   tcl_platform(%s):%s",tcl.String(key),tcl.String(tcl.Get(tcl_platform,key)) );
    }
    tcl.Unref(tcl_platform);
    tcl.Unref(names);
  }
  delete tcl;
  ATcl_OnDeinit();
}

полная версия скрипта включена в дистрибутив ATcl MQL4/Scripts/ATcl/version.mq4

MQL как базовый язык трейдинговой платформы довольно неплох в плане удобства и скорости рассчётов. Просто дополняйте его возможностями Tcl - интегрируйте свои Индикаторы и Эксперты с СУБД, системой, сетевыми сервисами и другими приложениями используя пакеты Tcl.

Размещайте ваши скрипты так как вам кажется удобным. Можете хранить их в одном системном каталоге и сипользовать из нескольких экземпляров MetaTrader и других проектов. Я предпочинаю держать скрипты с c:\forex\tcl .

#include <ATcl\\ATcl.mqh>
ATcl *tcl;
int ReadScripts(ATcl *tcl) {
  if (tcl==NULL || !tcl.Ready()) {
    return TCL_ERROR;
  }
  tcl.Eval("source c:/forex/tcl/script.tcl"); 	// загрузить все необходимые скрипты
  tcl.Eval("source c:/forex/tcl/script2.tcl"); 	// вы можете использовать / так-же как \\ как разделитель пути
}
void OnStart() {
  ATcl_OnInit();
  tcl=new ATcl;
  ReadScripts(tcl);	// загрузить необходимые скрипты в интерпретатор
  ...
  ATcl_OnDeinit();
}

Неплохой идеей является также организация скриптов в пакеты tcl и использование автозагрузки команд и пакетов

Хотя функции tcl можно вызывать из любого места программы методами Call и Eval, лучшим решением будет делать интерфейсные функции и классы скрывающие механику работы с интерпретатором.

#include <ATcl\\ATcl.mqh>
ATcl *tcl=0;
Tcl_Obj localMscProc=0;
// LocalMsc(); текущее системное время с точностью до милисекунд
// в остальном MQL коде использовать эту функцию вместо tcl.LongCall(localMscProc)
long LocalMsc() {
  return tcl.LongCall(localMscProc);	  
}
 
void OnStart() {
  ATcl_Init();
  tcl=new ATcl;
  localMscProc=tcl.Ref(tcl.Obj("localMsc"));
  tcl.Eval("proc localMsc {} { clock clicks -milliseconds }");
  ...
  tcl.Unref(localMscProc);  
  ATcl_OnDeinit();
}

Как и MQL, Tcl предоставляет все возможности для объектно-ориентированного программирования. Как на уровне базового языка OO, так и за счёт его расширений itcl, XOtcl, Next-Scripting

Пример использования элементарного класса tcl в классе MQL:

Stack.tcl
#!/usr/bin/tclsh
oo::class create Stack {
	variable data
	constructor {} {
		set data {}
	}
	destructor {
	}
	method Push { value } {
		lappend data $value
	}
	method Pop {} {
		set value [ lindex $data end ]
		set data [ lrange $data 0 end-1 ]
		return $value
	}
	export Push Pop
}
oostack.mq4
#include <ATcl\\ATcl.mqh>
ATcl *tcl;
 
class Stack {
protected:
   Tcl_Obj obj;
public:
   Stack() {
      obj=tcl.ObjEval("Stack new");
      tcl.Ref(obj);
   }
   ~Stack() {
      tcl.Call(obj,tcl.Obj("destroy"));
      tcl.Unref(obj);
   }
   void Push(string s) {
      tcl.Call(obj,tcl.Obj("Push"),tcl.Obj(s));
   }
   string Pop() {
      return tcl.StringCall(obj,tcl.Obj("Pop"));
   }
};
 
void OnStart()
{
   ATcl_OnInit();
   tcl=new ATcl;
   if (tcl!=NULL && tcl.Ready()) {
      if (tcl.Eval("source MQL4/Files/ATcl/Stack.tcl")!=TCL_OK) {
         PrintFormat("Error: %s",tcl.StringResult());
      } else {
         Stack stack;
         stack.Push("hello");
         stack.Push("word");
         PrintFormat("pop: %s",stack.Pop());
         PrintFormat("pop: %s",stack.Pop());
      }
   }
   delete tcl;
   ATcl_OnDeinit();
}

Tcl предоставляет библиотеку tcltest используемую во многих системах тестирования ПО. Иcпользуйте её для построения системы тестов ваших скриптов.