отрывок из моего кода.
Sig - сигнал: -1/0/+1 - продавать/закрывать/покупать
Aggression - коэффициент <=1.0 - доля от макс. разрешенной позиции, которой можно оперировать за раз.
cp - текущая позиция, шт.: <0/0/>0 - шорт/пусто/лонг
P - текущая цена (при работе робота по закрытию бара - цена закрытия бара)
Код: Выделить всё
 if(Sig!=0)
 {
  var FI=GetFinInfo();
   
  if(Sig>0)                               // индикатор пошел в рост
  {
   double AvailMoney=CurrentMoney;           // наличные
   int n=(int)(AvailMoney/P);                // сколько штук можно купить
   n/=FI.Lot;                                // сколько можно купить лотов
   n*=FI.Lot;                                // сколько штук можно купить с учетом лотов
   int ns=(cp<0 ? cp+n : n);                 // сколько из них пойдет в лонг
   int maxAllowed=(int)MaxLongAllowed();
   if(ns>maxAllowed) ns=maxAllowed;
    
   if(ns>0)
   {                                         // будет лонг
    double rate=(cp>0 ? cp/(cp+ns) : 0.0);   // текущий уровень затаривания
    rate+=Aggression; if(rate>=0.95) rate=1.0;
    ns=(int)(ns*rate/FI.Lot);                // лотов с учетом к-та агрессии
    if(ns==0) ns=1;                          // взять как минимум один лот
    ns*=FI.Lot;
    if(ns>maxAllowed) ns=maxAllowed;         // на всякий случай
   }
        
   if(ns>0) EnterLong(ns); else  // закроет шорт, если был, и купит ns; без шорта добавит ns
   if(ns<0) CloseShort(n); else  // сокращение шорта сколько можно (денег на полное закрытие не хватает)
   if(cp<0) CloseShort();         // ns=0: закрытие шорта, если был (денег хватает)
  } else
  
  if(Sig<0)                                // индикатор начал падать
  {
   double AvailMoney=CurrentMoney;           // наличные
   if(cp>0) AvailMoney+=2.0*cp*P;            //  + актив в лонге, доступный для покрытия шорта
   else AvailMoney+=2.0*cp*AverPrice();      //  - пассив для покрытия шорта
            
   int n=(int)(AvailMoney/P);                // сколько всего можно продать
   n/=FI.Lot;                                // сколько можно продать лотов
   n*=FI.Lot;                                // сколько штук можно продать с учетом лотов
   int ns=(cp>0 ? cp-n : -n);                // сколько из них пойдет в шорт
    
   int maxAllowed=(int)MaxShortAllowed();
   if(ns<-maxAllowed) ns=-maxAllowed;
   if(ns<0)
   {                                         // будет шорт
    double rate=(cp<0 ? cp/(cp+ns) : 0.0);   // текущий уровень затаривания
    rate+=Aggression; if(rate>=0.95) rate=1.0;
    ns=(int)(ns*rate/FI.Lot);                // лотов с учетом к-та агрессии
    if(ns==0) ns=-1;                         // продать как минимум один лот
    ns*=FI.Lot;
    if(ns<-maxAllowed) ns=-maxAllowed;       // на всякий случай
   }
     
   if(ns<0) EnterShort(-ns); else  // закроет лонг, если был, и продаст ns; без лонга продаст еще ns
   if(cp>0) CloseLong();             // закрытие лонга (это всегда доступно)
  } // Sig<0
 } // Sig!=0
 /*
 else
 { // Sig==0
  if(cp!=0) ClosePosition();
 } // Sig==0
 */
Как-то так.