Добрый вечер. Признаю опыта программирования у меня нет вообще, очень понравился всем известный индикатор Squeeze Momentum Indicator, даже нашел версию для МТ4, но вот для Квик сколько не искал всё бестолку. Прошу помочь перекодить его для квик. Прилагаю код из трейдингвью. С большим уважением к Вам.
//+------------------------------------------------------------------+ //| Created for MT4 by Ravish A | //| Ravish Anandaram | //| mailto: aravishstocks@gmail.com | //+------------------------------------------------------------------+ // =========================================================================================================== // This indicator is based on a strategy mentioned in John Carter's book, Mastering the Trade. // It is also a fully improvised version of Squeeze_Break indicator by DesO'Regan. // You can find that implementation here: // https://www.mql5.com/en/code/8840?utm_campaign=MetaTrader+4+Terminal&utm_medium=special&... // The main improvements include plotting squeeze values (some BB/KC calculation changes) on the zero-line and then to smoothen the momentum values as rising/falling positive/negative histograms // to match the ones sold on commercial websites. This is easy on the eye. // Uses some of the Linear Regression code fr om Victor Nicolaev aka Vinin's V_LRMA.mq4 for smoothening the histograms // This version DOES NOT have any alerts functionality and also does not have inputs to change. // The reason is - this is V1 and generally no body changes the BB and KC values. Feel free to enhance on your own. // And if you like this indicator pa$$ :-) on to --> Ravish Anandaram (aravishstocks@gmail.com) // =========================================================================================================== #property copyright "Ravish Anandaram (aravishstocks@gmail.com)" #property link "mailto: aravishstocks@gmail.com" //+------------------------------------------------------------------+ //| indicator properties | //+------------------------------------------------------------------+ #property indicator_separate_window #property indicator_buffers 6 #property indicator_color1 MediumBlue #property indicator_color2 Tomato #property indicator_color3 DodgerBlue #property indicator_color4 Orange #property indicator_color5 ForestGreen #property indicator_color6 Red //+------------------------------------------------------------------+ //| Buffer Array Declarations | //+------------------------------------------------------------------+ double Squeeze_Off[]; // Green Dots on the zero line double Squeeze_On[]; // Red Dots on the zero line double SqzFiredLong_Strong[]; // Rising Positive Histograms double SqzFiredShort_Strong[]; // Falling Negative Histograms double SqzFiredLong_Weak[]; // Falling Positive Histograms double SqzFiredShort_Weak[]; // Rising Negative Histograms //+------------------------------------------------------------------+ //| Internal Global Variables | //+------------------------------------------------------------------+ int Bollinger_Period=20; double Bollinger_Deviation=2.0; int Keltner_Period=20; double Keltner_ATR=1.5; int Bollinger_MaMode=MODE_SMA; int Keltner_MaMode=MODE_SMA; int BarsToGoBack=1000; int Smooth_Factor=10; double LSmoothX=1.0; double LSmoothY=1.0; double LSmoothFactor_1=3.0; double LSmoothFactor_2=3.0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { IndicatorDigits(4); // indicator value precision //--- Indicator Setup SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(0,SqzFiredLong_Strong); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(1,SqzFiredShort_Strong); SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(2,SqzFiredLong_Weak); SetIndexStyle(3,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(3,SqzFiredShort_Weak); SetIndexStyle(4,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(4,Squeeze_Off); SetIndexStyle(5,DRAW_HISTOGRAM,EMPTY,3); SetIndexBuffer(5,Squeeze_On); //--- Indicator Labels IndicatorShortName("Squeeze RA V1"); //--- return(0); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { ObjectsDeleteAll(); return(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ double GetSmoothenedValuesForHistograms(int nShift,int nLength) { double LSmooth1,LSmooth2,LSmoothVal; LSmooth1=LSmoothX*iMA(Symbol(),0,nLength,0,MODE_SMA,PRICE_CLOSE,nShift); LSmooth2=iMA(Symbol(),0,nLength,0,MODE_LWMA,PRICE_CLOSE,nShift)/LSmoothY; LSmoothVal=LSmoothFactor_1*LSmooth2-LSmoothFactor_2*LSmooth1; return LSmoothVal*Smooth_Factor; } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { //--- Indicator Optimization int Counted_Bars=IndicatorCounted(); if(Counted_Bars < 0) return -1; if(Counted_Bars>0) Counted_Bars=Counted_Bars-Keltner_Period; int limit=Bars-Counted_Bars; int lim it2=0; //--- if(_Period==PERIOD_MN1) Smooth_Factor= 4; else if(_Period == PERIOD_W1) Smooth_Factor= 4; else if(_Period == PERIOD_D1) Smooth_Factor= 6; else if(_Period == PERIOD_H4) Smooth_Factor= 8; else if(_Period == PERIOD_H1) Smooth_Factor= 30; else if(_Period == PERIOD_M30) Smooth_Factor= 50; else if(_Period == PERIOD_M15) Smooth_Factor= 50; else if(_Period == PERIOD_M5) Smooth_Factor= 100; else if(_Period == PERIOD_M1) Smooth_Factor= 300; //--- Main Indicator Loop for(int i=limit-2; i>=limit2; i--) //main indicator FOR loop { //--- Indicator Calculations double Kelt_Mid_Band=iMA(Symbol(),0,Keltner_Period,0,Keltner_MaMode,PRICE_CLOSE,i); double Kelt_Upper_Band = Kelt_Mid_Band + (iATR(Symbol(),0,Keltner_Period,i)*Keltner_ATR); double Kelt_Lower_Band = Kelt_Mid_Band - (iATR(Symbol(),0,Keltner_Period,i)*Keltner_ATR); //--- double StdDev=iStdDev(Symbol(),0,Bollinger_Period,0,Bollinger_MaMode,PRICE_CLOSE,i); double Ma=iMA(Symbol(),0,Bollinger_Period,0,Bollinger_MaMode,PRICE_CLOSE,i); double Boll_Upper_Band = Ma + (StdDev*Bollinger_Deviation); double Boll_Lower_Band = Ma - (StdDev*Bollinger_Deviation); //--- double dLSmoothVal=0; //--- Buffer Calculations //--- Smoothen the histogram bars using linear reg methods dLSmoothVal=GetSmoothenedValuesForHistograms(i,Keltner_Period); if(dLSmoothVal>0) { if((SqzFiredLong_Strong[i+1]!=0 && dLSmoothVal>SqzFiredLong_Strong[i+1]) || (SqzFiredLong_Weak[i+1]!=0 && dLSmoothVal>SqzFiredLong_Weak[i+1])) { SqzFiredLong_Strong[i]=dLSmoothVal; SqzFiredLong_Weak[i]=0; } else { SqzFiredLong_Weak[i]=dLSmoothVal; SqzFiredLong_Strong[i]=0; } SqzFiredShort_Strong[i]=0; SqzFiredShort_Weak[i]=0; } else { if((SqzFiredShort_Strong[i+1]!=0 && dLSmoothVal<SqzFiredShort_Strong[i+1]) || (SqzFiredShort_Weak[i+1]!=0 && dLSmoothVal<SqzFiredShort_Weak[i+1])) { SqzFiredShort_Strong[i]=dLSmoothVal; SqzFiredShort_Weak[i]=0; } else { SqzFiredShort_Weak[i]=dLSmoothVal; SqzFiredShort_Strong[i]=0; } SqzFiredLong_Strong[i]=0; SqzFiredLong_Weak[i]=0; } //--- if(Boll_Upper_Band<Kelt_Upper_Band && Boll_Lower_Band>Kelt_Lower_Band) { Squeeze_On[i]=0.01; Squeeze_Off[i]=0; } else { Squeeze_Off[i]= 0.01; Squeeze_On[i] = 0; } } // end of main indicator FOR loop //--- return(0); } //+------------------------------------------------------------------+
function Init()
indicator:name("Squeeze Momentum Indicator");
indicator:description("");
indicator:requiredSource(core.Bar);
indicator:type(core.Oscillator);
indicator.parameters:addGroup("Calculation");
indicator.parameters:addInteger("lengthKC", "KC Length", "", 20, 2, 2000);
indicator.parameters:addGroup("Style");
indicator.parameters:addColor("Up", "Up Color", "", core.#00ff00);
indicator.parameters:addColor("Down", "Down Color", "", core.#ff0000);
indicator.parameters:addColor("Neutral", "Neutral Color", "", core.#808080);
end
-- Indicator instance initialization routine
-- Processes indicator parameters and creates output streams
-- Parameters block
local first;
local source = nil;
local MA, Average,Raw;
local Alert;
local close_local_up, local_ex_up;
local close_local_dn,local_ex_dn;
local val;
local lengthKC;
local Up,Down,Neutral;
-- Routine
function Prepare(nameOnly)
lengthKC= instance.parameters.lengthKC;
local name = profile:id() .. "(" .. instance.source:name() .. ", " .. lengthKC .. ")";
instance:name(name);
Up= instance.parameters.Up;
Down= instance.parameters.Down;
Neutral= instance.parameters.Neutral;
if (nameOnly) then
return;
end
close_local_up = instance:addInternalStream(0, 0);
local_ex_up = instance:addInternalStream(0, 0);
close_local_dn = instance:addInternalStream(0, 0);
local_ex_dn = instance:addInternalStream(0, 0);
val = instance:addInternalStream(0, 0);
MA= instance:addInternalStream(0, 0);
Average= instance:addInternalStream(0, 0);
Raw = instance:addInternalStream(0, 0);
source = instance.source;
first=source:first()+lengthKC;
Alert = instance:addStream("Alert" , core.Bar, " Alert"," Alert",instance.parameters.Neutral, first+lengthKC);
Alert:setPrecision(math.max(2, instance.source:getPrecision()));
end
-- Indicator calculation routine
function Update(period, mode)
if period < first then
return;
end
MA[period]= mathex.avg(source.close, period-lengthKC+1, period);
Average[period] = ((source.high[period]+source.low[period])/2 + MA[period])/2;
Raw[period]= source.close[period]-Average[period];
if period < first+lengthKC then
return;
end
val[period] =mathex.lreg ( Raw, period-lengthKC+1,period);
if(val[period]>0 and val[period]<val[period-1] and val[period-1]>val[period-2]) then
local_ex_up[period]= val[period]
else
local_ex_up[period]=local_ex_up[period-1]
end
if val[period]>0 and val[period]<val[period-1] and val[period-1]>val[period-2] then
close_local_up[period]=source.close[period]
else
close_local_up[period]=close_local_up[period-1]
end
if val[period]<0 and val[period]>val[period-1] and val[period-1]<val[period-2] then
local_ex_dn[period]=val[period]
else
local_ex_dn[period]=local_ex_dn[period-1]
end
if val[period]<0 and val[period]>val[period-1] and val[period-1]<val[period-2] then
close_local_dn[period]=source.close[period]
else
close_local_dn[period]=close_local_dn[period-1]
end
if (close_local_up[period]>close_local_up[period-1] and local_ex_up[period-1]>local_ex_up[period]) then
dn_sg=true;
else
dn_sg=false;
end
if (close_local_dn[period]>close_local_dn[period-1] and local_ex_dn[period-1]>local_ex_dn[period]) then
dn_sg_custom=true;
else
dn_sg_custom=false;
end
if (close_local_dn[period]<close_local_dn[period-1] and local_ex_dn[period-1]<local_ex_dn[period]) then
up_sg=true;
else
up_sg=false;
end
if (close_local_up[period]<close_local_up[period-1] and local_ex_up[period-1]<local_ex_up[period]) then
up_sg_custom=true;
else
up_sg_custom=false;
end
if dn_sg or dn_sg_custom or up_sg or up_sg_custom then
Alert[period]=1;
else
Alert[period]=0;
end
if( val[period] >val[period-1]) then
Alert:setColor(period, Up);
elseif( val[period] < val[period-1]) then
Alert:setColor(period, Down);
else
Alert:setColor(period, Neutral);
end
end
Ради интереса посмотрел на индикатор. Проблема в том, что везде разный код. А первоистчника нет. В одном месте линейная регрессия одна, в другом другая. В третьем вижу, что выводят линейную регрессию как гистограмму, что нонсенс, т.к. это прямая.
Если Вы скачали файлы с GitHub, то необходимо провести конвертацию файла в кодировку 1251, т.к. на сайте все хранится в UTF-8. Также не забудьте положить рядом файл maLib.lua т.к. индикатор зависит от нее. Впрочем, это видно из кода.
Nikolay написал: необходимо провести конвертацию файла в кодировку 1251
Всё сделал. По прежнему в списке нет. Проверял на 8.4 и 8.6 версиях Квика. Впрочем остальные ваши индикаторы и без конвертации прекрасно работали. Вот файл, если интересно https://cloud.mail.ru/public/Efiq%2FRCqtM3y3d А еще в 8.6 перестал работать priceAvgProfile. К сожалению Квик не выдает, на какой строчке ошибка :-(
Добавьте файл индикатора в окно доступные скрипты: Сервисы - Lua скрипты. Запустите его. Будет показана ошибка компиляции. Именно она не дает добавить индикатор в список. Файл я посмотрел - он в правильно кодировке.
Также обновил priceAvgProfile. Напомнили, он был не совместим с lua 5.3
Nikolay написал: Также обновил priceAvgProfile. Напомнили, он был не совместим с lua 5.3
файл обновил. вижу 29 отличий, но на версии Квик 8.6 все равно ошибка «attempt to compare number with string». Вариант с загрузкой LuaIndicators как LuaScripts тоже не работает. они даже никаких ошибок не выдают. может на 7 Квике это работало, но на 8 — нет...
Ну раз у Вас нет ошибок при запуске индикатора как скрипта а я его вижу перед глазами в версии > 8.5, то, скорее всего, не подгружается maLib через require('maLib')
Можете заменить загрузку библиотеки такой конструкцией: _G.load = _G.loadfile or _G.load local maLib = load(_G.getWorkingFolder().."\\Luaindicators\\maLib.lua")()
Либо пропишите пути поиска библиотеки через package.path
Что касается priceAvgProfile, то тоже вижу его перед собой. Но возможно, у Вас проблема в данных и надо отловить ошибку. Посмотрю еще на разных бумагах.
Nikolay написал: Можете заменить загрузку библиотеки такой конструкцией:_G.load = _G.loadfile or _G.loadlocal maLib = load(_G.getWorkingFolder().."\\Luaindicators\\maLib.lua")()
Про прощение задержку ответа, эта конструкция заработала. priceAvgProfile тоже (не понятно, что было не так, может нулевые значения цен), но почему то начиная с 8 версии (любой) изменение параметра Period никак не влияет на результат. в 7 версии индикатор меняется от смены параметра. В идеале бы добавить опцию зеркального отображения с прилипанием к правому краю окна, но это не принципиально