#354
00000
Цитата

for (int i=0; 0


Может i...?
Ну и тралит он на каждом тике, а желательно, по свечам.

Например:
Спойлер

//+------------------------------------------------------------------+
void Tralling()
{
double timepr;
if(timepr == Time[0]) return(0);
timepr = Time[0];

double ima1 = iMA(Symbol(), PERIOD_M30, Peri, 0, MODE_SMA, PRICE_CLOSE, 1);

for (int i=0; i {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType())
{
SL = NormalizeDouble(ima1, Digits);
if (OrderStopLoss() != SL)
OrderModify(OrderTicket(), OrderOpenPrice(), SL, 0, 0);
}
}
}
}
//+------------------------------------------------------------------+

Изменено 23 августа, 2013 пользователем Vorchunozavr

#355

Я свою функцию немного подрихтовал, попробуй, внешние переменные в шапку:

Спойлер

extern int Repids=2;
extern int TralBuySize=30;
extern int TralSellSize=30;
extern bool TralProfitOnly=True;
void SimpleTral()
{
int i, k;
double ima1 = iMA(Symbol(), PERIOD_M30, Peri, 0, MODE_SMA, PRICE_CLOSE, 1);
SL = NormalizeDouble(ima1, Digits);
for (i=0; i {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if (OrderType()==OP_BUY)
{
if (TralProfitOnly==False || Bid-OrderOpenPrice()>TralBuySize*Point)
{
if (OrderStopLoss() {
for (k=1;k {
if (OrderModify(OrderTicket(), OrderOpenPrice(), SL, OrderTakeProfit(), 0, NULL)) break;
Sleep(1);
}
}
}
}
if (OrderType()==OP_SELL)
{
if (TralProfitOnly==False || OrderOpenPrice()-Ask>TralSellSize*Point)
{
if (OrderStopLoss()> SL || OrderStopLoss()==0)
{
for (k=1;k {
if (OrderModify(OrderTicket(), OrderOpenPrice(), SL, OrderTakeProfit(), 0, NULL)) break;
Sleep(1);
}
}
}
}
}
}
}
return;
}



Добавлено: 23-08-2013 13:31:29

А вообще довольно поверхностное построение функции.
1 - Возможно сползание стоп лоса вопреки логики.
2- непонятно что делать если модификация неполучилась.

Спойлер

void Tralling()
{
double ima1 = iMA(Symbol(), PERIOD_M30, Peri, 0, MODE_SMA, PRICE_CLOSE, 1);
SL = NormalizeDouble(ima1, Digits); //вынесем за цикл чтоб мощьности не тратил постоянный пересчет
for (int i=0; i {
if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType())// хз зачем тут это сравнение и с чем сравнивать, поэтому удаляем ее
{

if (OrderStopLoss() != SL) //все понятно , но здесь кроется проблема №1 что писал выше
OrderModify(OrderTicket(), OrderOpenPrice(), SL, 0, 0);
}
}
}
return;//машина это дурак которому нужно все объяснять на пальцах чтоб исключить инокотолкований лучше всего указать точку выхода принудительно
}

Изменено 23 августа, 2013 пользователем Ttomas

#356


Название советника: Сеточник- пробойник (название изменено)



а почему название изменено? можно хотябы ответить в личку его оригеналное название? покапаться в интернете,может отыщется чтонибудь дельное по этому сову.


Разлочил...
Ошибки кой-какие поправил. Остались некоторые, если будет интерес - поправим и остальные...

Версия 2.1
---
P.S.:
ммммда...
$790 как-то многовато за такое :)



заинтересовал сов. можно всётаки его доисправить? даже в тестере ошибки 130 не дают нормально его оценить.

Добавлено: 25-08-2013 11:23:32

ещё вопросы :
этот сов работает только с евробаком? (другие пары он у меня даже тестить не хочет,а евробакс с ошибками)
если да,то есть возможность "отвязать" от этой пары?
импульсы на вход в рынок сов ищет на каком TF? можно также отвязать от этого,вывядя как отдельную настройку?

Изменено 25 августа, 2013 пользователем VINTOZAVR

#357


А вообще довольно поверхностное построение функции.
1 - Возможно сползание стоп лоса вопреки логики.
2- непонятно что делать если модификация неполучилась.



Не то чтобы возможно - если набрать пачку ордеров - сползает и довольно ощутимо x(
#358

Здравствуйте. Подскажите пожалуйста.

Советник открывает ордер на продажу как только появилась красная стрелка. Затем когда появилась зеленая он закрыл ордер и купил.
Как реализовать следующее.
Например при появлении красной стрелки мы продаем, после этого появляется опять красная мы опять отрываем ордер на продажу , затем когда появляется зеленая мы закрываем все ордера на продажу и открываем на покупку ? После просмотра уроков по MQL я немного написал, но как двигаться дальше не понимаю.

Спойлер


берем из индикатора данные

PriceLow = iCustom( Symbol(), 0, "indi", 0, 0);
PriceHigh = iCustom(Symbol(), 0, "indi", 1, 0);

if( Ask >= PriceHigh && CountBuy() == 0 )
{
TP = NormalizeDouble( Ask - TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask + StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,5,0,0,"",Magic,0,Blue);

if(ticket > 0)
{
OrderModify(ticket, OrderOpenPrice(), SL, TP, 0, CLR_NONE);
}
}

//Считаем количество открытых ордеров BUY
int CountBuy()
{
int count=0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic )
{
if(OrderType() == OP_BUY)
count++;
}
}
return(count);
}


То есть как мне открыть второй ордер если CountBuy() не дает так как уже не равна 0 ?

Если функция CountBuy() убираю то ордера открываются на каждом тике. :(

Изменено 4 сентября, 2013 пользователем Samuilus

#359

Насамом деле есть много вариантов решения. Но так как тут ордер может открыться в середине бара то можно просто ограничить 1 ордером в бар, функция что тут добавлена - из учебника.
Алгоритм работы прост, задаем переменную что торговля на этом баре не проводилась, если появился новый бар то подтверждаем что торговля не проводилась, если совершился трейд то устанавливаем в TRUE - торговля на этом баре совершалась. Тогда торговая операция на этом же баре не совершится дважды, а только на новом.

Спойлер

static bool TradOnThisBar=false;

PriceLow = iCustom( Symbol(), 0, "indi", 0, 0);
PriceHigh = iCustom(Symbol(), 0, "indi", 1, 0);

if (fNewBar()==True) TradOnThisBar=false;

if( Ask >= PriceHigh && TradOnThisBar==false )
{
TP = NormalizeDouble( Ask - TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask + StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_SELL,Lots,Bid,5,0,0,"",Magic,0,Blue);

if(ticket > 0)
{
OrderModify(ticket, OrderOpenPrice(), SL, TP, 0, CLR_NONE);
TradOnThisBar=True;
}
}


bool fNewBar()
{
static datetime NewTime=0;
if(NewTime!=Time[0])
{
if(NewTime==0)
{
NewTime=Time[0];
return(false);
}
NewTime=Time[0];
return(true);
}
return(false);
}



Удачи в изысканиях! \M/
#360

Вот спасибо тебе добрый человек буду дерзать !!! >:d:d:d


Добавлено: 03-09-2013 16:39:12

А может как то другим способом сделать проверку на появления стрелки, ну например на следующем баре ?

Добавлено: 03-09-2013 16:52:31

Я бы хотел понять как реализовать следующее:
открывается новый бар и идет проверка - если над предыдущем баром есть стрелка тогда открываем ордер независимо куда пошла цена. Подскажите кто знает как реализовать плиз

Изменено 3 сентября, 2013 пользователем Samuilus

#361

Элементарно и просто=) PriceLow = iCustom( Symbol(), 0, "indi", 0, 0); 0 - текущий бар 1 -предыдущий=).

#362

Спасибо большое, но подскажи мне пожалуйста вот еще что. Каким образом определить стрелку не как цену а как bool или еще как то.
Ну например открылся новый бар, бы обращаемся к предыдущему и если есть стрелка то 1 если нет то например 0 и на этом основании или открываем ордер или нет

#363

Это тоже просто=) я обычно сигнал вывожу как отдельную функцию наподобии:

Спойлер

bool SigBuy ()
{
if (iCustom(Symbol(), 0, "ZZ", ZigDepth, ZigLabel, 1, ZigShift)!=0 && SecSigB==True) return(True);
return(false); //иначе говорим что сигналов на покупку нет
}



или же взять как условие:

Спойлер

if (iCustom(Symbol(), 0, "ZZ", ZigDepth, ZigLabel, 1, ZigShift)!=0) {набор опервторов}



помню тоже были непонятны такие мелкие тонкости, но раз сделав запомнишь =)
Стрелки в индюках обычно идут в отдельном буфере, и поэтому в остальных случаях этот буфер пуст, поэтому и сравниваем с нулем, кстати если не получится с нулем то вместо него введи EMPTY_VALUE.
#364

СПАСИБО !!!
так всего много и непонятно аж интересно :)


Добавлено: 04-09-2013 07:16:47

опять непонятки смотри сделал так

Спойлер


start()
-------------------------------
static bool TradOnThisBar=false;


if (fNewBar()==True) TradOnThisBar=false;

if( Signal () == true )
{
ticket = 0;
TP = NormalizeDouble( Ask + TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask - StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_BUY,Lots, Ask, Slippage, 0,0, "", Magic,0,Blue);
if(ticket >0)
{
OrderModify(ticket,OrderOpenPrice(),SL,TP,0,CLR_NONE);
TradOnThisBar=True;
}
}
----------------------------------
return(0);
----------------------------------


bool fNewBar()
{
static datetime NewTime=0;
if(NewTime!=Time[0])
{
if(NewTime==0)
{
NewTime=Time[0];
return(false);
}
NewTime=Time[0];
return(true);
}
return(false);
}

------------------------------------------------------------------

bool Signal ()
{
if (iCustom(Symbol(), 0, "zz", 0, 1)!=EMPTY_VALUE )
return(True);
return(false);
}
--------------------------------------------------------------------



Да на следующем баре после сигнала открывает ордера но открывает их на каждом тике пока не закрылся бар

Добавлено: 04-09-2013 07:22:03

Заключил в ковычки вроде работает незнаю правильно или нет ?
Спойлер



start()
-------------------------------
static bool TradOnThisBar=false;


if (fNewBar()==True)
{
TradOnThisBar=false;

if( Signal () == true )
{
ticket = 0;
TP = NormalizeDouble( Ask + TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask - StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_BUY,Lots, Ask, Slippage, 0,0, "", Magic,0,Blue);
if(ticket >0)
{
OrderModify(ticket,OrderOpenPrice(),SL,TP,0,CLR_NONE);
TradOnThisBar=True;
}
}

}
----------------------------------
return(0);
----------------------------------


bool fNewBar()
{
static datetime NewTime=0;
if(NewTime!=Time[0])
{
if(NewTime==0)
{
NewTime=Time[0];
return(false);
}
NewTime=Time[0];
return(true);
}
return(false);
}

------------------------------------------------------------------

bool Signal ()
{
if (iCustom(Symbol(), 0, "zz", 0, 1)!=EMPTY_VALUE )
return(True);
return(false);
}
--------------------------------------------------------------------


Изменено 4 сентября, 2013 пользователем Samuilus

#365

Здесь ты забыл добавить условие что на этом баре небыло трейда. Поэтому и неработает. Данный вариант больше подходит если у тебя сигнал появляется в середине бара, и в функции сигнала "zz" это я брал индюк для своей функции, у тебя должен быть свой индюк=) не переименновывать же каждый, а если их у тебя 10 или 15?=)


Спойлер

start()
-------------------------------
static bool TradOnThisBar=false;


if (fNewBar()==True) TradOnThisBar=false;

if( Signal () == true && TradOnThisBar==false )//Забыл ты чтото маленько=)
{
ticket = 0;
TP = NormalizeDouble( Ask + TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask - StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_BUY,Lots, Ask, Slippage, 0,0, "", Magic,0,Blue);
if(ticket >0)
{
OrderModify(ticket,OrderOpenPrice(),SL,TP,0,CLR_NONE);
TradOnThisBar=True;
}
}
----------------------------------
return(0);
----------------------------------


bool fNewBar()
{
static datetime NewTime=0;
if(NewTime!=Time[0])
{
if(NewTime==0)
{
NewTime=Time[0];
return(false);
}
NewTime=Time[0];
return(true);
}
return(false);
}

------------------------------------------------------------------

bool Signal ()
{
if (iCustom(Symbol(), 0, "zz", 0, 1)!=EMPTY_VALUE ) return(True); //здесь это упорядоченно смотрится
return(false);
}
--------------------------------------------------------------------


Второй вариант впринципе должен работать, но тогда у тебя есть лишние операции, а это лишние затраты ресурсов сервера и времени на выполнения программы. Если советник будет совершаться только на новом баре то надобности в предложенном мной варианте нет.
Спойлер

start()
-------------------------------
if (fNewBar()==True)
{
if( Signal () == true )
{
ticket = 0;
TP = NormalizeDouble( Ask + TakeProfit * Point, Digits);
SL = NormalizeDouble( Ask - StopLoss * Point, Digits);
ticket = OrderSend(Symbol(),OP_BUY,Lots, Ask, Slippage, 0,0, "", Magic,0,Blue);
if(ticket >0)
{
OrderModify(ticket,OrderOpenPrice(),SL,TP,0,CLR_NONE);
}
}

}
----------------------------------
return(0);
----------------------------------


bool fNewBar()
{
static datetime NewTime=0;
if(NewTime!=Time[0])
{
if(NewTime==0)
{
NewTime=Time[0];
return(false);
}
NewTime=Time[0];
return(true);
}
return(false);
}

------------------------------------------------------------------

bool Signal ()
{
if (iCustom(Symbol(), 0, "zz", 0, 1)!=EMPTY_VALUE ) return(True);
return(false);
}
--------------------------------------------------------------------



И вообще, совет который мне дал когда-то преподаватель по робототехнике мне очень помог. Хотябы поначалу ставь напротив каждого оператора комментарий с описанием его действия, причем достаточно подробным, тогда не будешь путаться и сразу поймешь где что ты забыл или неуказал, и вскоре сможешь читать даже чужой код очень просто. Успехов!
#366

Огромное спасибо , что поправил, и советом наставил, буду учиться, я просто всего неделю изучаю MQL, до этого изучал PHP


Добавлено: 04-09-2013 11:04:03

А насчет индикатора, конечно я свой подставляю :)

Добавлено: 04-09-2013 11:10:51

Вот сейчас прогнал за август с 2 по 31 ,
пара: GBP-USD
депо: 10 000
TAKEPROFIT = 100 pips
спред = 10
STOPLOSS=0
сделки только на BUY (на SELL надо обратный код прикрутить )


Добавлено: 04-09-2013 11:15:33

111.jpg
222.jpg

Изменено 4 сентября, 2013 пользователем Samuilus

#367

Выглядит слишком хорошо=) только когда закончишь его писать сделай тест на 90% на котировках 2х-3х брокеров, а то у меня тоже один скальпер на альпах на истории за 5 лет делал 64 миллиона с 1к баксов, вроде и просадки были и спред ночью 41 для теста использовал, результаты конечно отличались но профит был налицо=), я решил неверить и прогнал на терминале робофорекса с их котировками, результаты были в разы меньше но тоже в +, а вот тест на центовике за 3 месяца сказал что он тихо но сливает, так что история историей но проверяй на реале однозначно!!!=)

#368

Хорошо так и сделаю, на VPS нужно будет поставить его.


Добавлено: 04-09-2013 13:00:55

Послушай Ttomas а какой хороший индикатор тренда можно взять? Хочу фильтровать сделки.

Добавлено: 04-09-2013 13:19:43

я вот думал определить тренд по МА тоесть не по цене за последние 15-20-30 баров а именно по значению МА за последние там сколько то баров а вот как это сделать , я тут думаю что мне нужно как то так тоесть берем текущее значение МА затем откручиваем 20 баров например и берем значение опять МА и если есть сигнал на покупку и текущее значение MA больше чем то, которое 20 баров назад, значит советник покупает :)

Изменено 4 сентября, 2013 пользователем Samuilus

#369

Хорошего или идеального индикатора тренда небывает наверное. все они врут, а также врет и МА так как опаздывает=) Ну если ты хочешь сделать определение тренда по МА то вызови ее через iMA и в последнем переданном параметре выбери сколько баров назад. У тебя как я понял скальпер, поэтому тебе следует обращать больше внимания на краткосрочные и\или экспоненциальные МА тогда просто сравни МА на 0\1 баре с МА на 1\2 или как вариант сравни разности между (0\1 и 1\2) и (1\2 и 2\3) чтоб понять ускоряется ли тренд в данном направлении.

Но опять таки свежий пример из жизни, с полчаса назад собрал очень простой скальпер,(проще только орел решка) дает результат 53 к 47 , но средниий тп к сл 17.9 к 19.3 сделок много сделал и поэтому в + отторговал 5 лет , подумал, а почему б не добавить элементарный фильтр по МА. Итог сливает. как не крутил и не оптил - сливает. Вывод - как говорил Павел : "Не все йогурты одинаково полезны".

#370

Да все верно про йогурты :).
Я просто не знаю по какому еще индикатору можно определить тренд мне вот тут видео попалось и на нем линия идет посмотри пожалуйста. Мне просто интересно что это за линия ползет такая ровная ? Ма ?
youtube.com/watch?v=Bo_YWA-FkZw

#371

Если четсно, то да, похожа на МА, наверное тяжелую (100-300) а вот тип и цену я незнаю, врятле экспонента, также врятле линейновзвешенная, мб или обычная или смурфид. А цена, ну по крайней мере перерисовывается слабо то может быть как по ценам открытия, но и нельзя исключать другие. Хотя это может быть и совсем другой индикатор. если ты используешь большие ТФ то может быть тебе стоит попробывать вот такой подход:

Спойлер

ищем последние 2 экстремума вверх и 2 экстремума вниз если они все направленны в одну сторону, то торгуем в этом направлении, возможны варианты, например выбирать экстремум как в рыбалке, или же как в индикаторе демарка. 1 вариант будет более красткосрочным так как экстремумом считается больший бар из 3х расположенный по центру. А в 2 варианте можно будет подстраивать как 1 из 3-х, 1 из 5-ти, 1 из 7-ми и другие... Причем можно брать, допустим главное направление 1из5, а подтверждение 1из3. Но это просто мысли вслух из задумок на будущее, из реализации ясно что надо вызывать iCustom и из демарка выбивать буфера с минимумами и максимумами, а анализ делать в самом советнике. Рад буду если поможет.

#372

Спасибо очень интересно, попробую нечто организовать.


Добавлено: 05-09-2013 09:14:59

Подскажи мне пожалуйста правильно я понимаю следующее?
Мне нужно вернуть bool=true если цена закрытия больше цены открытия предыдущего бара ?


Спойлер


bool Bar()
{
double O = iOpen(Symbol(),0,1);
double C = iClose(Symbol(),0,1);

if(C > O) return(true);
return(false);
}


Изменено 5 сентября, 2013 пользователем Samuilus

#373

Верно, так как ты все делаешь на одном таймфрейме и на одной валюте, можно было все сделать много проще, а соответственно качественнее (Чем проще механизм тем реже он ломается (с)) :d :

Спойлер

bool bar()
{
if (Open[1] return(false);
}
#374

Спасибо! Подскажи мне добрым советом. Вот например возьмем ну например Стохастик, как мне вернуть bool если он зашел за уровень 20 или 80 ? :) plizzzzzzzzz

#375

Было бы отлично, если бы ты сам пытался понять механизм работы индикаторов, ведь их всего несколько типовых вариантов. Если взглянуть на стохастик, то он принимает значения только в диапазоне от 0 до 100. если посмотреть в его настройках - настройки цвета, то увидишь что нужный цвет самый верхний, это говорит что тебе нужен 0 номер буфера. Так как это стандартный индикатор мт4 то для ее вызова есть уже предопределенная функция iStochastic передаваемые параметры глянь в справке, или простым нажатием F1 на функции. А теперь чтоб получить значение bool тебе нужно провернуть абсолютно такую же операцию как и с функцией направления бара только сравнивать ты будешь iStochastic(...) с необходимым уровнем. Наподобии iStochastic(...)80. Чтоб достать сигнал из индикатора, надо понимать как он работает и куда и как дает сигналы. \M/


Добавлено: 05-09-2013 18:21:57

Еще перед тем как рассматривать стандартный индикатор загляни в стандартную справку MT4 раздел Аналитика \Технические индикаторы

Изменено 5 сентября, 2013 пользователем Ttomas

#376

Доброй ночи! Написал трейлинг, примерно похожий на написанный в уроке по MQL. Хотел достичь только одного действия - установки безубытка при указанном размере трейлинг-стопа. Логически вроде бы все правильно. Не работает. Без отладки крайне сложно понять, в чем ошибка, причем журнал все не показывает, останавливается практически сразу после установки ордера.
Работаю с демо-сервером финама, 5-знак. H4. Своп на демо-сервере происходит каждые сутки.

трейлинг.txt10 скач.

#377

Приветствую, мельком глянул твой код, заметил только одно замечание которое возможно и создают ошибку. переменную Ans нужно объявить заранее, потому что она локальная и объявлялась только в цикле на покупку, то есть при трале продаж такой переменной нет и соответственно ничего делать не будет.

Спойлер

void Trailing()
{
trailing_stop = 500;

for(int i = (OrdersTotal() - 1); i>=0; i--)
{
double SL;
bool Ans;
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
{
if (OrderSymbol() == Symbol())
{
if ((OrderType() == OP_BUY))
{
if(Bid - OrderOpenPrice() > NormalizeDouble(trailing_stop*Point,Digits))
{
SL = NormalizeDouble(OrderOpenPrice()+10*Point,Digits);
if (OrderStopLoss() != SL)
{
Alert(SL);
Ans=OrderModify(OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0);
}
}
}
if (OrderType() == OP_SELL) //Если цена ушла на trailing_stop пунктов вниз - делаем безубыток
{

if(OrderOpenPrice() - Ask > NormalizeDouble(trailing_stop*Point,Digits))
{
Alert("Попали в 1 условие");

Alert("Попали во 2 условие");
SL = NormalizeDouble(OrderOpenPrice()-10*Point,Digits);
if (OrderStopLoss() != SL)
{
Alert("Попали в модифи");
Ans=OrderModify (OrderTicket(),OrderOpenPrice(),SL,OrderTakeProfit(),0);
}
}
}
}
}
}
return; // тоже не помешает, если есть вход значит и выход желательно сделать, робот ведь дурак которого учат
}


А вообще непонятно зачем ты выполняешь модификацию при присвоении, ну будет у тебя эта переменная иметь значение но ты же с ней ничего не делаешь. Еще ты не проверяешь на совподение Магик номера, таким образом все ордера в терминале на данной паре тралится будут. Такие функции каждый подбирает под себя. я например взял кимовский трал и его же безубыток и переделал под себя сделав автономными при условии единства внешних переменных в своих совах.

Добавлено: 07-09-2013 21:38:35

Еще было бы неплохо добавить несколько попыток на трал, на случай если терминал занят другим ордером и незабудь про защиту от зацикливания.

Изменено 8 сентября, 2013 пользователем Ttomas

#378

Там один ордер на одной паре. Отлаживаю пока.

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025