Может ли чайник написать робота? Что два байта переслать! Глава 3.

25 января 2020, 18:13
Programmer96
[Удален]
0
113

Переменные

В этой главе кратко описано что такое переменная, каких они бывают типов и как с ними работать.
Массивы и структуры (это тоже переменные) описаны в общих чертах.
Подробный экскурс в массив массивов и структур будет сделан позже, это отдельная большая тема. 
На первых порах можно успешно писать роботов не используя массивы и структуры. _______________________________________________________________________________________________________________________

Содержание 

  • Введение
  • Первый шаг
  • Основы языка
  • Переменные 
  • Функции
  • Учимся читать
  • Обучение методом "Ломаем/строим". Модификация чужого кода
  • Работа над ошибками
  • Как найти "иголку" в стоге кода функции которую якобы можно использовать "как есть"?
  • Графический интерфейс
  • Пишем простой советник с нуля
  • Пишем сеточный советник с Мартингейлом
  • Перечень вложений
   В предыдущей главе были перечислены основные типы данных. Они же являются и типами переменных.
Ниже более длинный список возможных типов переменных:
   • char, short, int, long, uchar, ushort, uint, ulong – целые числа;
   • color – целое число, представляющее RGB-цвет;
   • datetime – дата и время, число равное количеству секунд, прошедших с 1 января 1970г.
   • bool – логические значения true и false;
   • double – числа двойной точности с плавающей точкой;
   • float – числа одинарной точности с плавающей точкой;
   • string – символьные строки.

Объявление переменных

     Имена переменных должны быть уникальными и написаны латиницей. Имя обязательно должно начинаться с буквы (строчной или прописной - неважно) или знака подчеркивания. Начиная со второго знака можно использовать цифры.
    Настоятельно рекомендую давать переменным осмысленные имена, иначе вы очень скоро начнете с трудом понимать свой собственный код.
   Переменные должны быть объявлены перед их использованием, иначе ошибка.
Переменные бывают локальными и глобальными.

    Локальные переменные это те, которые объявлены внутри функции или составного выражения. Они видны только там где объявлены. В другой функции может быть объявлена локальная переменная с тем же именем.
    Пример объявления локальных переменных:
int open(double lot=0,double tpVal=0,double slVal=0, int mag=0, string comment="") { 
// Переменные принимающие данные объявляются в () после имени функции
  double LastMar=ND2(AccountMargin()); 
//локальные переменные используемые только в этой функции.
  int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); 
  int orderNumber=0;
/*
    Блок операторов
*/
   return(orderNumber); 
 } //-- int open

  Глобальные переменные объявляются за пределами функций, в так называемом глобальном пространстве. Переменные входящих параметров это глобальные переменные.
Переменные объявленные ниже входных параметров или еще ниже, в промежутках между функциями - это тоже глобальные переменные. Где бы они ни были размещены (хоть после самой последней функции), они всегда будут выше, так как программа вначале читает глобальное пространство и только потом OnInit(), OnTick() и вызванные из них  пользовательские функции.
   Глобальные переменные видны из любого места программы.

    Пример объявления глобальных переменных:
.... ....
sinput string  d01="====== DrawDown close ================";  
input int      LossTP               =-250;        
sinput bool    ByClose              =false;
sinput bool    SeClose              =false;
sinput bool    SecondToClose        =false;
input int      TaxStartClosing      =35;    //taxStartСlosing
input int      DropConstant         =50;
sinput bool    TaxClosing           =true;  
input  int     TaxPercent           =50;   
sinput bool    NextClosing          =true; 
input  int     NextPercent          =65;     
input int      Lot4cls              =30;   //% Unit for nextClose 
input double   pairClsAll           =1;    //% ClsAll_on_Pair <0 ==OFF
input int      EquityDifferClsALL   =5;    //% EquityDifferClsALL <0 ==OFF
sinput int     ZeroPercent          =10;
// ==========================================
 int SleepPage=15;
 string txt="";
 double dk, spr, taxPerc=0, nextPerc=0, rsiDif,osDif, MK; 
 bool BSok=0,SSok=0, BLok=0,SLok=0, 
      maON, fastON, shortON, rsiON, osON, bigLimON,minLimON, 
      BLmini=0,SLmini=0, 
      miniBLcheck=0,miniSLcheck=0, stopBScheck=0,stopSScheck=0, 
      bl_check=0,sl_check=0, check_step=true,
      bAuto1, sAuto1, bAuto2, sAuto2, LevTr_ON;  
 bool diagram=true, stLineShow=true, LimLineShow=false, pyrLnShow=false, 
      arrDeleted=false,
      reInvest, TradeStop=false, TradeStart=false;
 int sp, pyrLimPer,  nextOrdLim,
     firstLevPer,LevNLper, nextLevPer,  bigLimPer, minLimPer,
     offset,maPer,fPer,maDif,fastDif, shortDif,sPer, 
     rsiTF,rsiPer=0, osTF, osPer=0,
     bs_TP=0,ss_TP=0,  bl_TP=0,sl_TP=0, bNxtTP=0,sNxtTP=0, next_FixTP, next_SafeTP,
     Lim_PyrTP=0, 
     bs_Dist=0,ss_Dist=0, fixStep, safeStep, LimStep=0, bl_Dist=0,sl_Dist=0, interval=0, 
     bTrSt=0, sTrSt=0, bNxtSt=0,sNxtSt=0, BaseDist=0, LevTrDist=0,NextLev_TrDist=0, 
     bigLimDif=0, minLimDif=0, pyrLimDif=0, startClose;

// ==========================================================================  
int OnInit() {
//--
{ .... } { .... }
//-----------
   return(INIT_SUCCEEDED);
 } //--   

   Наверняка кто-то да обратил внимание на комментарий в конце нескольких строк входящих параметров.
input int      Lot4cls              =30;   //% Unit for nextClose
 В этом случае это не совсем комментарий. В обновленной версии языка Это второе имя переменной, которое видит пользователь, но не программа. Писать можно любой текст на любом языке, с пробелами, знаками умножения, деления, доллара, процента и т.п. Длина строки не лимитируется. Эту же строку я мог написать так:
input int Lot4cls =30; //Квант объема для функции nextClose. % от начального лота.  


Инициализация переменных

      Инициализация переменных, это присваивание им какого-то начального значения. Инициализацию можно не делать если при первом обращении к переменной ей присваивается значение. Вот так, например:
int OnInit() {
//--
   firstLevPer=Lev1_Per; LevNLper=Lev1_NoLossPer; nextLevPer=Lev2_Per;
//-----------
   return(INIT_SUCCEEDED);
 } //--   
   Здесь промежуточные переменные приравниваются к константам входящих параметров.
Но, если переменная впервые используется в каком-либо условном выражении, то компилятор выдаст вам предупреждение: "Возможно использование  не инициализированной переменной". В большинстве случаев вред ограничивается только замечаниями компилятора, но иногда использование не инициализированной переменной  может иметь печальные последствия. Поэтому от греха подальше (и чтобы не заморачиваться) - присваивайте всем переменным начальное значения при их объявлении.

   Есть еще один тип глобальных переменных - GlobalVariables == Глобальные переменные терминала. Эти функции-переменные видны из другого советника или индикатора. С их помощью можно координировать работу советников. Лимитировать использования свободной маржи при мультивалютной торговле, например. Или передавать какой-то трендовый сигнал нужный нескольким советникам.
    Если имеются глобальные переменные этого типа, то их список и их текущие значения можно вывести во всплывающее окно нажатием клавиши F3.

Так как это может вам понадобиться, то дам здесь основные сведения об этом  типе переменных.  Остальное самостоятельно найдете в Документации, но для начала лучше в этом разделе учебника Ковалева, а потом в этом -  здесь есть полезный список ссылок.
   Проверяя работу ссылок просмотрел вновь то что там написано и решил - здесь ничего больше о глобальных переменных терминала писать не стану - все что нужно очень полно, но в то же время лаконично и доходчиво изложено Сергеем Ковалёвым ещё в 2008 году, мне к этому добавить нечего - снимаю шляпу


Сравнивание переменных

  Со сравниванием целочисленных переменных никаких проблем. Но, если это double or float, то могут быть проблемы. Во-первых обязательно нужно нормализовать сравниваемые переменные. Но и это далеко не всегда спасает. Иногда после нормализации даже до второго знака можно увидеть вывод: a=0.07000000001
Если  b==0.07; и мы пишем условие if(a==b) то в итоге можем получить полную фигню - понятно что цифра 0.07 аж никак не равна цифре 0.07000000001
  Лучше  писать не  ==   а   >=   или  <= 
Если же категорически требуется именно   ==  , то я знаю только одно надежное лекарство:
 double a=0.07000000001;      
   string check=DoubleToString(a,2);
   a=StringToDouble(check);

   И никаких проблем. Прогон переменной через строку гарантированно убирает мусорную единичку после надцатого знака. Лишние телодвижения? Некрасиво? Да, изяществом не блещет. Но работает надежно. И это главное.


Массивы и структуры

    это тоже переменные, но сложного и/или составного типа.

Массив - это индексированный набор однотипных данных.
   Например:
int arrayPrice [50]; // Одномерный массив из 50 целых чисел.
string arrayList [250]; // Строковой массив. Список работников, например
double SalaryBonusesAllowances [3][50]; 
/*  Двухмерный массив из трех массивов, каждый из которых состоит из 50 чисел.
    Суть многомерных массивов в том, что хранящиеся в них данные взаимосвязаны.
*/

     Подробнее о массивах будет написано позже, это отдельная объемная и сложная тема.
Пока что вы можете обходиться без использования массивов. 
 
  Структуры – это составные типы данных, построенные с использованием других типов.
struct MyTime  {
   int hour;    // 0-23
   int minute;  // 0-59
   int second;  // 0-59
}; //-- 
   О структурах буду писать где-то в конце учебника.
Если по чесноку, то за те почти 12 лет, что я пишу на MQL4, структуры использовал считанные разы. И не потому что не смог разобраться - разобрался, разложил все по полочкам еще в конце первого года писательства (когда впервые понадобилось). Следующий раз был года через 3-4 и так далее. В этом году тоже использовал структуру!!! (аж один раз - для закрытия профитных сделок и выключения советника перед концом сессии когда километровым спредом начинают стопы сбивать и включения где-то в 1:30 по терминальному - то и другое задается из менюшки )
    И шо ви себе думаете - это таки была структура типа Дата-Время ;-)
А вот если у вас хватит "мудрости" перейти на MQL5, то вы там буквально с первого шага (попытки адаптировать MQL4 под MQL5) столкнетесь со структурами которые напихали везде где тока мона - фиг сделку откроешь без использования структуры.     Зачем?!!!     Не понимаю...     
Ученость свою показать?  Показать программеру где обитает кузькина мать? Глупо как то.


ЗЫ
       Черновой вариант. Будет правиться.


   Ранее опубликованные посты (с августа 2014)