Codebase - теперь как не надо писать стратегии?
По ссылке https://protrader.org/codebase/strategies/chande-f...
очередной пример того, как не надо писать... теперь уже стратегии.
Итак:
public override void NextBar()
{
Run();
}
Для чего нужен метод Run() ?
Нельзя было все сделать в NextBar() ?
public override void OnQuote()
{
if (Positions.GetPositions().Where(p => p.MagicNumber == MagicNumber).Count() > 0)
{
foreach (var order in Orders.GetOrders())
{
order.Cancel();
}
}
}
Этот метод отменит вообще все ордера, даже не относящиеся к данной стратегии при обнаружении новой позиции. Врядли нам это нужно.
void Run()
{
if (CurrentData.Count < Math.Max(MAPeriod, regrPeriod))
return;
var v0 = cfo.GetValue(0, 1);
var v1 = cfo.GetValue(0, 2);
if (v0 > 0 && v1 <= 0)
{
NewRequest(Operation.Sell);
}
else if (v0 < 0 && v1 >= 0)
{
NewRequest(Operation.Buy);
}
}
Что мешало назвать переменные v0 и v1
cmo1 и cmo2 соответсвенно? Ведь они как раз содержат значения индикатора
cmo на первом и втором баре.
private void NewRequest(Operation side)
{
if (Positions.GetPositions().Where(p => p.MagicNumber == MagicNumber).Count() == 0)
{
double price = CurrentData.GetPrice(PriceType.Close, 1);
NewOrderRequest request1 = new NewOrderRequest()
{
Price = price + stopOffset * Point,
Side = Operation.Sell,
Type = OrdersType.Limit,
Amount = Amount,
Account = Accounts.Current,
MagicNumber = MagicNumber,
Instrument = Instruments.Current,
StopLossOffset = SL * Point,
TakeProfitOffset = TP * Point,
};
Orders.Send(request1);
NewOrderRequest request2 = new NewOrderRequest()
{
Price = price - stopOffset * Point,
Side = Operation.Buy,
Type = OrdersType.Limit,
Amount = Amount,
Account = Accounts.Current,
MagicNumber = MagicNumber,
Instrument = Instruments.Current,
StopLossOffset = SL * Point,
TakeProfitOffset = TP * Point,
};
Orders.Send(request2);
}
}
Этот метод еще раз выполняет проверку на наличие позиций,
и никак не использует переменную side. В любом случае он устанавливает
два ордера.
Возможно здесь должна была быть логика, устанавливающая один ордер
в зависимости от значения переменной side. Если это так, то зачем сначала
использовать логику для вычистения установки значения переменной side,
и затем использовать еще одноу логику учитывающую её значение,
когда можно было создать два метода SetBuyLimit() и SetSellLimit(),
и вызывать их примерно так (при этом проверку на наличие позиций сделать один раз):
if (cmo1 > 0 && cmo2 <= 0)
{
SetSellLimit();
}
else if (cmo1 < 0 && cmo2 >= 0)
{
SetBuyLimit();
}
Если же стратегия предусматривает установку двух ордеров одновременно,
то переменна side вообще не нужна.
Вот как бы сделал я, если предположить что направление индикатора все - же
учитывается при установке ордеров:
public override void NextBar()
{
// Если есть позиция с данным MagickNumber - выходим и ждем пока
// сработает SL или TP:
if (Positions.GetPositions().Where(p => p.MagicNumber == MagicNumber).Count() > 0)
return;
// Проверяем, нет ли установенных стратегией ордеров.
// Если есть - отменяем, потому что они были установлены в начале
// предыдущего бара и не сработали. Сигнал в одном и том же направлении
// два бара подряд существовать не может, и цена скорее всего уже ушла.
foreach (var order in Orders.GetOrders().Where(p => p.MagicNumber
== MagicNumber))
{
order.Cancel();
}
// Проверяем значение осциллятора и устанавливаем ордера:
if (cmo1 > 0 && cmo2 <= 0)
{
SetSellLimit();
}
else if (cmo1 < 0 && cmo2 >= 0)
{
SetBuyLimit();
}
}
Так будет намного проще и понятнее. Вся логика в одном методе, одна
проверка на наличие позиций. В стратегии, опубликованной на сайте,
кроме отмены ордеров, не относящихся к стратегии, возможна установка
неограниченного количества ордеров. Если при этом пропадет связь,
то мы получим нежелательные позиции. К тому же в зависимости от качества связи
и скорости изменения цен часть ордеров может сработать, часть отмениться.
В итоге эта стратегия будет работать правильно только в тестере.
Кому вообще она адресована? Для начинающих она даже вредна,
поскольку является примером, того, как не надо называть переменные и
строить логику. Для работы на реальном счете она непригодна.
Опытный трейдер знает, что стратегии вида "если что - то пересекает ноль
сверху вниз - продадем (или покупаем), снизу вверх - покупаем (или продаем)"
очень быстро сделает минус на счете. Прибыли конечно дождаться можно,
но наверное это один из наихудших способов потратить деньги и нервы.
Поэтому вместо примитивных плохо написанных однотипных стратегий
хотелось бы увидеть красивый код, учитывающий реалии торговли,
а так же в полной мере демонстрирующий возможности платформы PTMC.
P.S. Не смог оформить код как надо. Код становится
белым и сливается с фоном.
Этот метод отменит вообще все ордера, даже не относящиеся к данной стратегии при обнаружении новой позиции. Врядли нам это нужно.
Согласен. Проверка на MagicNumber отсутствует.
Что мешало назвать переменные v0 и v1
Для чего нужен метод Run() ?
В ходе тестирования работы стратегии логика метода Run() применялась как в запуске OnQuote() так и переносилась в NextBar(). Соответственно, названия переменных не было смысла переименовывать.
Да и если точнее сказать, то в данной реализации это уже значения второго и третьего бара, а не первого и второго.
Если же стратегия предусматривает установку двух ордеров одновременно,
то переменна side вообще не нужна.
Данная переменная нужна для передачи информации по какому пересечению будут выставляться ордера. В ходе написания стратегии использовались и другие комбинации отложенных ордеров, к примеру на BuyLimit & SellLimit и так же на BuyStop&SellLimit. А изначально, действительно было построено решение на использовании одного лимитного ордера и в зависимости от side выставлялась корректная цена и сторона лимитного ордера.
Нельзя было все сделать в NextBar() ?
Нет, нельзя.Так как SL/TP срабатывают не на баре, а на приходящую котировку. Соответственно, отмена ордера производится в OnQuote().
Каждая стратегия длительно подбирается, пишется, проверяется и тестируется неоднократно для того, чтобы найти максимально удачный вариант ее использования. В ходе этого процесса не исключены и ошибки. Но это не дает вам никакого права общаться со мной или скем-то другим в подобном роде, особенно начиная свои мысли с "очередной шедевр".
Повторюсь, не смотря ни на что, с вами никто не хочет иметь дел. Вы относитесь неуважительно как ко мне так и ко всем остальным.
Данный ответ я написал только из уваженния к нашему сообществу.
Да и если точнее сказать, то в данной реализации это уже значения второго и третьего бара, а не первого и второго.
Нет.
Метод NextBar() вызывается на первом тике нового бара, имеющего индекс "0".
Значит методы возвращают именно значения индикатора на первом и втором баре.
var v0 = cfo.GetValue(0, 1);
var v1 = cfo.GetValue(0, 2);
Да и если точнее сказать, то в данной реализации это уже значения второго и третьего бара, а не первого и второго.
Нет.
Метод NextBar() вызывается на первом тике нового бара, имеющего индекс "0".
Значит методы возвращают именно значения индикатора на первом и втором баре.var v0 = cfo.GetValue(0, 1);
var v1 = cfo.GetValue(0, 2);
Carlos Bahia
carlos.bahia.br@gmail.com