В прошлом году я решал подобную задачку. Просто для удобства оперирования с линиями тренда (мне нужно было, чтоб они всегда были строго горизонтальны) я сделал индикатор. Посмотрите мой код (файл приложен)- там при движении графика линии перемещаются вслед за ним. Чуть позже сниму и выложу маленькое видео. Пока же вот участок кода, на который стОит обратить внимание:
// ================================================================================================+ // ============= БЛОК ОБРАБОТКИ СОБЫТИЙ ============= | // ================================================================================================+ void OnChartEvent(const int id, // идентификатор события const long& lparam, // параметр события типа long (Координата Х мыши) const double& dparam, // параметр события типа double (Координата Y мыши) const string& sparam){ // параметр события типа string (Имя объекта, по которому кликнули) int x=0,y=0,window=0,lastindex=(-1); datetime DT=0; double PRr=0; if(id==CHARTEVENT_CLICK){ CheckLabelAll(); } if(BtnSostoyanie("BtClearTrLine")=="DOWN"){ if(id==CHARTEVENT_CLICK){ DeleteTrLines(); BtnPress("BtClearTrLine","UP"); } } // ------------- Создаём линию по клику мыши и нажатой кнопке ---------------- if(BtnSostoyanie("BtBuyTrLine")=="DOWN"){ //--- нажатие левой кнопкой мышки на графике if(id==CHARTEVENT_CLICK){ if(CountBuy>0){ CountBuy=0; x = (int)lparam; y = (int)dparam; // ------ Инициализируем будущие координаты if(ChartXYToTimePrice(0,x,y,window,TimeRight,PRr)){ lastindex = LastIndex(TimeRight); if(lastindex<0){ lastindex=5; } TimeRight=Time[lastindex]; TimeLeft=Time[lastindex+10]; TimeDotLeft=TimeRight; TimeDotRight=Time[lastindex-4]; PRr=NormalizeDouble(PRr,DGS); } // ------------ Зелёная линия ----------------- s_TrendLineName=StringConcatenate(SMB,"_",BuyTrendLine,"_Buy_",TimeLocal()); if(ObjectFind(s_TrendLineName)<0){ CreateTrendLine(0,s_TrendLineName,0,TimeLeft,PRr,TimeRight,PRr,GreenGroup,STYLE_SOLID,WidthTrendLine,false,true,false,false,0); ObjectSetInteger(0,"BtBuyTrLine",OBJPROP_STATE,false);// отжимаем кнопку if(ObjectFind(s_TrendLineName)>(-1)){// линия есть // --------- Генерируем имя Dot-линии ----------------- s_DotLineName=StringConcatenate("Dot_",s_TrendLineName); if(ObjectFind(s_DotLineName)<0){ TimeLeft=TimeRight; CreateTrendLine(0,s_DotLineName,0,TimeDotLeft,PRr,TimeDotRight,PRr,GreenGroup,STYLE_DOT,1,false,false,true,false,0); s_LabelName=StringConcatenate("LBL_",s_TrendLineName); DrawLABEL(Font,FontSize,s_LabelName,DoubleToString(PRr,DGS),3,y-18,CORNER_RIGHT_UPPER,LabelPriceColor); } } } else{ ObjectSetInteger(0,"BtBuyTrLine",OBJPROP_STATE,false);// отжимаем кнопку } } else{ CountBuy=1; } } } if(BtnSostoyanie("BtSellTrLine")=="DOWN"){ //--- нажатие левой кнопкой мышки на графике if(id==CHARTEVENT_CLICK){ if(CountSell>0){ CountSell=0; x = (int)lparam; y = (int)dparam; // ------ Инициализируем будущие координаты if(ChartXYToTimePrice(0,x,y,window,TimeRight,PRr)){ lastindex = LastIndex(TimeRight); if(lastindex<0){ lastindex=5; } TimeRight=Time[lastindex]; TimeLeft=Time[lastindex+10]; TimeDotLeft=TimeRight; TimeDotRight=Time[lastindex-4]; PRr=NormalizeDouble(PRr,DGS); } // ------------ Красная линия ----------------- s_TrendLineName=StringConcatenate(SMB,"_",SellTrendLine,"_Sell_",TimeLocal()); if(ObjectFind(s_TrendLineName)<0){ CreateTrendLine(0,s_TrendLineName,0,TimeLeft,PRr,TimeRight,PRr,RedGroup,STYLE_SOLID,WidthTrendLine,false,true,false,false,0); ObjectSetInteger(0,"BtSellTrLine",OBJPROP_STATE,false);// отжимаем кнопку if(ObjectFind(s_TrendLineName)>(-1)){// линия есть // --------- Генерируем имя Dot-линии ----------------- s_DotLineName=StringConcatenate("Dot_",s_TrendLineName); if(ObjectFind(s_DotLineName)<0){ CreateTrendLine(0,s_DotLineName,0,TimeDotLeft,PRr,TimeDotRight,PRr,RedGroup,STYLE_DOT,1,false,false,true,false,0); s_LabelName=StringConcatenate("LBL_",s_TrendLineName); DrawLABEL(Font,FontSize,s_LabelName,DoubleToString(PRr,DGS),3,y-18,CORNER_RIGHT_UPPER,LabelPriceColor); } } else{ ObjectSetInteger(0,"BtSellTrLine",OBJPROP_STATE,false);// отжимаем кнопку } } } else{ CountSell=1; } } } if( id==CHARTEVENT_OBJECT_CLICK){ LastObjName=sparam; } //if(id==CHARTEVENT_MOUSE_MOVE){ if(id==CHARTEVENT_MOUSE_MOVE && LastObjName!=""){ x = (int)lparam; y = (int)dparam; if(StringFind(LastObjName,"_Buy_",0)>(-1)){ CheckTrendLine(0,LastObjName);// ровняем линию - могли сместить CheckLabelLine(LastObjName); } if(StringFind(LastObjName,"_Sell_",0)>(-1)){ CheckTrendLine(0,LastObjName);// ровняем линию - могли сместить CheckLabelLine(LastObjName); //LastObjName=""; } } if(id==CHARTEVENT_OBJECT_DRAG || id==CHARTEVENT_OBJECT_CHANGE || id==CHARTEVENT_OBJECT_ENDEDIT){ //if(id==CHARTEVENT_OBJECT_DRAG || id==CHARTEVENT_OBJECT_CHANGE || id==CHARTEVENT_OBJECT_ENDEDIT || id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_OBJECT_CLICK){ if(StringFind(sparam,"_Buy_",0)>(-1)){ CheckTrendLine(0,sparam);// ровняем линию - могли сместить CheckLabelLine(sparam); } if(StringFind(sparam,"_Sell_",0)>(-1)){ CheckTrendLine(0,sparam);// ровняем линию - могли сместить CheckLabelLine(sparam); } } if(id == CHARTEVENT_OBJECT_DELETE){ DeleteObjects(0,StringConcatenate("Dot_",sparam)); DeleteObjects(0,StringConcatenate("LBL_",sparam)); } ChartRedraw(0); }
Посмотрите мой код (файл приложен)- там при движении графика линии перемещаются вслед за ним.
Спасибо за код, посмотрел. У вас MOUSE_MOVE срабатывает только после клика по объекту (через LastObjName), то есть лейблы обновляются только когда линию тащишь.
А если просто график двигаешь вертикально мышью — Лабелы стоят на месте, отсюда и лаги, такие как у меня были раньше...
Пока что я решил задачу так:
ловлю CHARTEVENT_CHART_CHANGE для зума/сдвига, плюс MOUSE_MOVE всегда активен (не только после клика по объекту), + таймер на 50мс как страховка.
ChartRedraw вызываю точечно, а не при любом событии в OnChartEvent — у меня на графике объектов дофига, по этому стараюсь их ставить экономно.
В итоге лейблы ходят за линиями ровно при любом способе перемещения графика — и мышью, и клавишами, и при зуме.
Проблема с подвисанием ЛАБЕЛов при вертикальном перемещении графика ушла.
В любом случае, спасибо за ответ!
Знаете, в таком случае я не понимаю, что же Вы конкретно хотите. Смотрите, моя линия тренда, перемещаемая мышью перемещает за собой и меттку, в которой автоматически меняется цена. В видео это видно. Давайте уйдём от терминов линия, лейба и примем термин "связка объектов" или "группа объектов". Когда в моим индикатором создаёте линию тренда, то на самом деле там не одна, а две линии: сплошная и пунктирная, уходящая лучом вправо. Плюс к этому метка. Я тяну сплошную линию и вслед за ней тянется и пунктирная и метка. То есть, мы перемещаем сразу всю связку объектов. В принципе, не важно, линии это или иные объекты, связанные между собой. Важно другое - перемещается вся группа. Я сейчас сделаю Вам ещё одно видео - там тоже связка объектов (это прямоугольники и метки) - подобие инструмента "Ордер" в терминале TradingView. Посмотрите, там перемещение происходит подобным же образом. Может это видео позволит нам уточнить формулировки.
Итак, объект, как связка, перемещается весь целиком. Но! Вы говорите о перемещении графика, причём, цитирую: "А если просто график двигаешь вертикально мышью..." Вот тут как раз и не понятно, что именно Вы имеете ввиду. График можно перемещать вправо-влево по горизонтали. Но график можно перемещать (масштабировать) и по вертикали - сжимать и растягивать. Смотрите, как только я переместил связку, она автоматически привязывается к координатам цена/время. Листаю график влево и связка уезжает вправо. То есть её координаты относительно свеч не меняются. Когда же сжимаю график по вертикали, у меня сжимается рост свечи и связка съезжает ниже. У меня связка движется относительно краёв экрана. Но она не движется относительно точки привязки к графику. Говоря простым языком, это похоже на то, как я зашёл в автобус - куда он поехал, туда и я поехал. Но что же хотите Вы, поясните.
Сейчас покажу ещё связку, как и обещал.
Ну вот вариант:
Ваш код:
Строка 26:
bool g_linesDrawn = false;
Строки 71-76:
//--- Движение/зум графика — мгновенно пересчитываем Y лейблов if (id == CHARTEVENT_CHART_CHANGE && g_linesDrawn) { UpdateLabelPositions(); ChartRedraw(); }
Я думаю, что здесь
UpdateLabelPositions()
ни когда не выполнится. Есть такая штука - Булева Алгебра. Там есть формулы. Одна из них такая: "А и ложь = ложь", где знак "=" - это эквиваленция. Иными словами: в Вашем случае получается:
if(id == ложь) { // выполнится только если id = ложь }
Вот ещё участок Вашего кода:
void OnTimer() { if (g_linesDrawn && g_labelsVisible) { UpdateLabelPositions(); ChartRedraw(); } }
Здесь функция
UpdateLabelPositions();
не выполнится, ибо ранее проинициализированы ложью обе переменные
g_linesDrawn && g_labelsVisible
Ложь и ложь даст ложь. Вот основные таблицы истинности:
Ну вот вариант:
(точнее плавание объектов в рамках связки приемлемое, учитывая специфику МТ4).
Подозреваю что в этом варианте использованы объекты OBJ_TEXT. Но это не так важно на самом деле.
На счёт выполнения условий, возможно вы не обратили внимания на ХотКей H.
Переменные g_linesDrawn и g_labelsVisible инициализируются false , да — но они меняются на true в функции DrawLines() , которая вызывается по нажатию H.
После того как линии нарисованы, оба условия выполняются нормально.
Файл с решением которое использую сейчас, приложил. (добавлен MOUSE_MOVE и Страховочный таймер 50мс)
И да, вы были правы - связка используются на графике с фиксированным масштабом.
Я не стал скачивать Ваш второй файл кода. По-моему у Вас и с первым всё нормально. Посмотрите видео (включите звук в колонках чуть громче - у меня микрофон не очень - не компьютерный). Первые слова невнятны в ролике. Я там сказал: "Доброго времени суток"
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования

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