Добрый день, Уважаемые читатели. Продолжим разбор блочной структуры Робота на основе стратегии StepByStep.
Блок №8. Важный блок. тут происходит работа с уровнями при изменении количества акций при покупке или продажи Роботом.
//корректировка уровней
if(pos > xPosition)//позиция увеличилась
{
while (lastPriceSorted.Count > 0 && lastPriceSorted.First().Value <= 0)
lastPriceSorted.Remove(lastPriceSorted.First().Key);
int Qty2process = (int)(pos - xPosition);
double Lvl = GetSignalInfo(SignalType.Open, Qty2process)[0].PriceOfTrade;
var signal_1 = GetLastSignalInfo();
if (signal_1 != null && signal_1.ActionType == AvailableActions.ChangePosition) lastSignalProcessed = 0;
while (pos > xPosition) {
if(lastPriceSorted.ContainsKey(Lvl)) {
if (Q <= (int)lastPriceSorted[Lvl]) Qty2process = 0; // есть уровень
else Qty2process = (int)Math.Min(Q - (int)lastPriceSorted[Lvl], pos - xPosition);
lastPriceSorted[Lvl] += Qty2process;
} else { // нет уровня
Qty2process = (int)Math.Min(Q, pos - xPosition);
lastPriceSorted.Add(Lvl, Qty2process);
}
Lvl *= (1.0 + 0.01*DeltaPercentBuyNew);
lastSignalProcessed += Qty2process;
xPosition += Qty2process;
}
}
else if(pos < xPosition && lastPriceSorted.Count >= 1)
{
var b = xPosition;
while(b > pos)
{
if(lastPriceSorted.Count == 0) break;
var firstKey = lastPriceSorted.First().Key;
if(b - pos<lastPriceSorted[firstKey])
{
lastPriceSorted[firstKey] -= (b - pos);//Исполнили часть уровня
b -= (b - pos);
}
else
{
b -= lastPriceSorted[firstKey];//Исполнили весь уровень
lastPriceSorted.Remove(firstKey);
}
}
}
xPosition = pos;//позиция учтена выше
if (LastMinPrice != 0 && lastPriceSorted.Count <= 0)
{
MinPrice = LastMinPrice;
}
else
{
if(lastPriceSorted.Count <= 0)
{
MinPrice = StartPrice;
}
else
{
MinPrice = lastPriceSorted.First().Key;
LastMinPrice = MinPrice;//Запоминаем текущий MinPrice, что бы запомнить при распродаже в 0
}
}
Это один из важнейших блоков Робота. в этом блоке происходит работа с уровнями, добавляются уровни при покупке удаляются уровни при продаже, изменяется количество акций если была произведена только частичная покупка или продажа уровня. В этом же блоке производится обработка уровней при ручном вводе или изменении позиции.
Блок №9. Экспериментальный. Покупка акций для заполнения уровня да параметра Q.
Тут должен находится новый блок, который я приведу в примечании к этой статье. Дело в том, что многих интересует вопрос экономного расходования КЭШа, тем более в свете падения котировок рынка летом 2024 года, которое надеюсь завершилось, но полной уверенности еще нет.
Идеи заложенной в данный блок следующая. В процессе длительной работы Робота неизбежно возникнут ситуации, когда уровни продаются частично или вы со временем решили увеличить число акций на уровне и для этого увеличили значение параметра Q. в результате у вас получится, что число акций на "старых" уровнях будет меньше текущего значения Q. То есть при продаже уровня на котором число акций меньше Q вы теряете в доходности от продажи данного уровня. Поэтому пришла мысль, что когда начинается работа с таким уровнем, то есть резон докупить акции до размера нового Q пока цена будет меньше или равна цене торгуемого уровня.
Дальнейшее развитие идеи заключается в следующем. При падении цены акций закупать не число акций равное Q, а число акций равное одному лоту, а докупать уровень до Q уже когда цена акций растет тем самым забирать весь профит при росте, и экономно расходуя КЭШ при падении. Проблема состоит в том, что бы научить робота не докупать Q акций на падающем рынке, а это не просто, так как мы заранее не знаем где "дно рынка" и рынок падает не отвесно, а с коррекциями во время падения, когда уровни тоже продаются.
Все легко решается если при запуске Робота расставить уровни StartQ по одному лоту, и как сказано выше, при частичной продаже акций уровня или при увеличении значения параметра Q. КЭША тратится меньше а выхлоп получаем по максимуму. В общем еще есть над чем подумать.
Этот блок выкладывается именно в приложении, так как идея уже у меня работает, но не оформлена до конца и возможно не все ее захотят использовать. Тогда Робота можно собрать без этого блока.
Блок №10. Покупка уровня.
//Правило 2. Если цена упала и кол-во меньше допустимого,
// то покупаем и добавляем цену покупки в начало списка
if (Input1.Low[0] <= MinPrice* (1.0 - 0.001 * DeltaPercentBuy1) && pos + Q <= LongLimit || (xPosition == 0 && inited))
{
if(activeOrder != null && !activeOrder.IsStatusTerminal)
{
if(activeOrder.OrderDirection != OrderDirection.Buy) CancelActiveOrders(true);
SaveGlobalVars();
return;//ждём исполнения уже выставленной заявки
}
// если все распродал покупаем Q
if (xPosition == 0 && inited)
{
EnterLong(Q);
}
else
{
Delta = (LastPriceCount - (StartQ/Q));
DeltaPercentBuyNew = DeltaPercentBuy + kBuy*Delta;
SaveGlobalVars();
EnterLongLimit(Math.Min(MinPrice* (1.0 - 0.001 * DeltaPercentBuyNew ), Input1.Close[0]*(1.0 + 0.01 * OrderSlippage)), Q);
}
var lastSignal = GetLastSignalInfo();
if(lastSignal != null)
{
lastSignalId = lastSignal.SignalID;
lastSignalProcessed = 0;
}
}
Этот блок производит покупку акций для уровня когда цена падает на заданный нами процент. В отличии от стандартного Робота, тут происходит корректировка необходимого процента на который должна упасть цена для осуществления покупки, процент корректируется в зависимости от количества уже набранных уровней. Такой подход экономит нам КЭШ, так как чем больше уровней мы уже купили, тем больше должна упасть цена для следующей покупки.
Эту функцию можно отключить выставив коэффициент равным нулю.
Блок №11. Продажа уровня.
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
if (Input1.High[0] >= MinPrice* (1.0 + 0.001 * DeltaPercentSell1) && pos > 0 )
{
if(activeOrder != null && !activeOrder.IsStatusTerminal)
{
if(activeOrder.OrderDirection != OrderDirection.Sell) CancelActiveOrders(true);
SaveGlobalVars();
return;//ждём исполнения уже выставленной заявки
}
var vSell = (int)lastPriceSorted.First().Value;
Delta = (LastPriceCount - (StartQ/Q));
DeltaPercentSellNew = DeltaPercentSell + kSell*Delta;
SaveGlobalVars();
CloseLongLimit(MinPrice* (1.0 + 0.001 * DeltaPercentSellNew), vSell);
var lastSignal = GetLastSignalInfo();
if(lastSignal != null)
{
lastSignalId = lastSignal.SignalID;
lastSignalProcessed = 0;
}
}
SaveGlobalVars();
}
Этот блок производит продажу уровня когда цена повысится на заданную вами в настройках величину.
В этом блоке, я, по многочисленным просьбам, сделал возможность задавать процент роста цены для продажи независимым от процента падения для покупки. Но, что бы не снижать возможную доходность, то есть брать максимум возможного, процент роста цены для продажи, должен быть не меньше процента цены для покупки, оптимально делать их равными.
Поясню, почему это так. Допустим мы поставим падение цены для покупки равное 2%, а рост цены для продажи равным 1%. Тогда у нас купленные уровни будут располагаться на расстоянии друг от друга в 2%, и если мы продадим уровень при росте цены на 1%, то цена должна вырасти еще на процент, что бы достич цены покупки уровня, а затем еще на 1%, что бы этот уровень продать. По итогу цена должна вырасти на 2% (1%+1%=2%), а прибыль мы получим равную только в 1%. То есть 1% дохода мы недополучаем..
Приложение.
Вот для желающих Блок №9.
//Правило 1.5. Если цена упала, восстанавливаем до Q нижний уровень
if (lastPriceSorted.Count > 0 &&
Input1.Low[0] <= lastPriceSorted.First().Key &&
lastPriceSorted.First().Value < Q &&
LongLimit > pos &&
Q > 0 )
if(activeOrder != null) {
if(activeOrder.OrderDirection != OrderDirection.Buy) CancelActiveOrders(true);
return; // ждём исполнения уже выставленной заявки
}
double pBuy = lastPriceSorted.First().Key;
int qBuy = (int)Math.Min(LongLimit - pos, Q - lastPriceSorted.First().Value);
EnterLongLimit(pBuy, qBuy);
var lastSignal = GetLastSignalInfo();
if(lastSignal != null) {
lastSignalId = lastSignal.SignalID;
}
}
Теперь, Уважаемые подписчики вам остается собрать все блоки последовательно в единый файл в любом текстовом редакторе, например в блокноте. Скопировать весь полученный текст в "Библиотеку стратегий", кликнув по кнопке "Новая стратегия". Не забудьте после копирования скомпилировать и сохранить результат. И можете создавать на основе стратегии Роботов и зарабатывать деньги.
PS. Что бы не запутаться при копировании блоков в скобках, ошибка в скобках не позволит скомпилировать файл Робота. ЗАВТРА выложу вам полный текст Робота, файл проверен компиляцией.