Esempio n. 1
0
        protected async Task <bool> PanicSell(TradeTask tt)
        {
            try
            {
                await tt.locker.WaitAsync();

                // there could be BUY or SL orders running. cancell all them first.
                var result = await CancellAllOrders(tt);

                tt.Jobs.ForEach(x => tt.FinishedJobs.Enqueue(x));
                tt.Jobs.Clear();
                if (tt.Qty > 0)
                {
                    var sellJob = new OrderTask()
                    {
                        Symbol   = tt.Symbol,
                        Type     = OrderType.MARKET,
                        Kind     = OrderKind.PanicSell,
                        Side     = TradeSide.Sell,
                        Quantity = tt.Qty
                    };
                    tt.Jobs.Insert(0, sellJob);
                }
                TradeTaskViewModel.SerializeModel(tt);
                return(result);
            }
            finally
            {
                tt.locker.Release();
            }
        }
Esempio n. 2
0
        private async Task <bool> GetOrders(TradeTask tt)
        {
            foreach (var job in tt.FinishedJobs.Where(IsActiveJob))
            {
                var result = await GetOrder(job);

                job.ExchangeOrder = result;
                result.Fills.ForEach(x => tt.RegisterTrade(x));
            }

            if (tt.LastGetOrder.AddSeconds(5) <= DateTime.Now)
            {
                foreach (var job in tt.Jobs.Where(IsActiveJob))
                {
                    var result = await GetOrder(job);

                    if (job.ExchangeOrder == null || result.Updated > job.ExchangeOrder?.Updated)
                    {
                        job.ExchangeOrder = result;
                        tt.Updated        = DateTime.Now;
                        TradeTaskViewModel.SerializeModel(tt);
                        var ttvm = TradeTasksList.SingleOrDefault(x => x.Model == tt);
                        ttvm.Status = BuildStatusString(tt, job);
                        result.Fills.ForEach(x => tt.RegisterTrade(x));
                    }
                    tt.LastGetOrder = DateTime.Now;
                }
            }
            return(true);
        }
Esempio n. 3
0
 public TakeProfitViewModel(TradeTaskViewModel tt, OrderTask model, TakeProfitViewModel prev = null) : base(tt, model)
 {
     Previous = prev;
     if (Previous != null)
     {
         qtyPercentStart = Previous.QuantityPercentEnd;
     }
     qtyPercentEnd = qtyPercentStart + model.QuantityPercent;
     ConnectProperties();
 }
Esempio n. 4
0
 public TakeProfitViewModel(TradeTaskViewModel tt, double initialQtyPrcnt, TakeProfitViewModel prev = null) : base(tt)
 {
     Previous = prev;
     if (Previous != null)
     {
         QuantityPercentStart = Previous.QuantityPercentEnd;
         this.ObservableForProperty(x => x.Previous.QuantityPercentEnd).Subscribe(x => QuantityPercentStart = x.Value);
     }
     QuantityPercentEnd = QuantityPercentStart + initialQtyPrcnt;
     ConnectProperties();
 }
Esempio n. 5
0
 public OrderTaskViewModel(TradeTaskViewModel tt)
 {
     Model     = new OrderTask();
     TradeTask = tt;
     // TODO: OBPH
     this.WhenAnyValue(x => x.Price, x => x.Quantity, (rate, qty) => rate * qty)
     .ToPropertyEx(this, vm => vm.Total);
     this.WhenAnyValue(x => x.Price)
     .Subscribe(x => Model.Price = x);
     this.WhenAnyValue(x => x.Quantity)
     .Subscribe(x => Model.Quantity = x);
 }
Esempio n. 6
0
 public OrderTaskViewModel(TradeTaskViewModel tt, OrderTask model)
 {
     Model     = model;
     TradeTask = tt;
     Price     = model.Price;
     Quantity  = model.Quantity;
     this.WhenAnyValue(x => x.Price, x => x.Quantity, (rate, qty) => rate * qty)
     .ToPropertyEx(this, vm => vm.Total);
     this.WhenAnyValue(x => x.Price)
     .Subscribe(x => Model.Price = x);
     this.WhenAnyValue(x => x.Quantity)
     .Subscribe(x => Model.Quantity = x);
 }
Esempio n. 7
0
        private async Task <bool> CancellAllOrders(TradeTask tt)
        {
            var result = false;

            foreach (var job in tt.Jobs.Where(IsActiveJob).ToList())
            {
                result = await CancelOrder(job);

                tt.FinishedJobs.Enqueue(job);
                tt.Jobs.Remove(job);
                TradeTaskViewModel.SerializeModel(tt);
            }
            return(result);
        }
Esempio n. 8
0
        // before running the lifecycle, update ALL task orders
        // with status = ACTIVE | PARTIALLY_FILLED.

        private async Task Lifecycle(TradeTask tt, PriceTicker ticker)
        {
            if (!tt.Jobs.Any())
            {
                // Shutdown the task.
                tt.Status  = TradeTaskStatus.Finished;
                tt.Updated = DateTime.Now;
                tt.Events.Add(tt.Updated, "Task finished.");
                TradeTaskViewModel.SerializeModel(tt);
                return;
            }

            bool isLimitOrdersAllowed = true;

            // NOTE: this routine relies on condition that
            // LIMIT orders are always on TOP of MARKET orders in list of jobs.
            foreach (var job in tt.Jobs.ToList())
            {
                if (job.ExchangeOrder != null)
                {
                    switch (job.ExchangeOrder.Status)
                    {
                    case OrderStatus.Cancelled:
                        tt.Status  = TradeTaskStatus.Stopped;
                        tt.Updated = DateTime.Now;
                        tt.Events.Add(tt.Updated, "Task stopped due to order was cancelled outside.");
                        TradeTaskViewModel.SerializeModel(tt);
                        return;

                    case OrderStatus.Filled:
                        if (job.Kind == OrderKind.StopLoss)
                        {
                            // Shutdown the task.
                            tt.Status  = TradeTaskStatus.Finished;
                            tt.Updated = DateTime.Now;
                            tt.Events.Add(tt.Updated, "Task finished by stop loss.");
                        }
                        else if (job.Kind == OrderKind.PanicSell)
                        {
                            tt.Status  = TradeTaskStatus.PanicSell;
                            tt.Updated = DateTime.Now;
                            tt.Events.Add(tt.Updated, "Task stopped by panic sell.");
                        }
                        tt.FinishedJobs.Enqueue(job);
                        tt.Jobs.Remove(job);
                        TradeTaskViewModel.SerializeModel(tt);
                        return;

                    case OrderStatus.Active:
                    case OrderStatus.PartiallyFilled:
                        // THIS STATE IS ONLY POSSIBLE FOR LIMIT ORDERS OR PANIC SELL!
                        // so allow ONLY MARKET order to check conditions and execute
                        isLimitOrdersAllowed = false;
                        break;
                    }
                }
                else
                {
                    bool applicable   = false;
                    bool isLimitOrder = (job.Type == OrderType.LIMIT || job.Type == OrderType.STOP_LIMIT);
                    // check condition
                    if (job.Kind == OrderKind.Buy)
                    {
                        applicable = (tt.StopLoss.Price < ticker.Ask) && (ticker.Ask < tt.TakeProfit.First().Price);
                        if (!applicable)
                        {
                            var ttvm = TradeTasksList.SingleOrDefault(x => x.Model == tt);
                            ttvm.Status = "Цена вне зоны покупки";
                        }
                    }
                    else if (job.Kind == OrderKind.PanicSell)
                    {
                        applicable = true;
                    }
                    else
                    {
                        applicable = (job.Type != OrderType.MARKET && job.Type != OrderType.TRAILING) || (ticker.Bid >= job.Price); // NOTE: last part is wrong -- could be market STOP_LOSS, so ticker.Bid <= job.Price is valid for this case
                    }
                    // !!!ALLOW ONLY 1 LIMIT ORDER AT A TIME FOR NOW!!!
                    if (applicable && (isLimitOrdersAllowed || !isLimitOrder) && (tt.Qty > 0 || job.Side == TradeSide.Buy))
                    {
                        var result = await CancellAllOrders(tt);

                        if (job.Side == TradeSide.Sell)
                        {
                            // Do not sell more then you have :D
                            job.Quantity = Math.Min(tt.Qty, job.Quantity);
                        }

                        job.ExchangeOrder = await ExecuteOrder(job);

                        job.OrderId = job.ExchangeOrder.OrderId;
                        tt.Updated  = DateTime.Now;
                        tt.Events.Add(tt.Updated, $"Created order {job.OrderId}.");
                        TradeTaskViewModel.SerializeModel(tt);
                        job.ExchangeOrder.Fills.ForEach(x => tt.RegisterTrade(x));

                        var ttvm = TradeTasksList.SingleOrDefault(x => x.Model == tt);
                        ttvm.Status = BuildStatusString(tt, job);
                    }
                    return; // exit for
                }
            }
        }