Exemple #1
0
        private void AddActiveOperation(Operation op)
        {
            this._ActiveOperations.Add(op);
            var symData = GetSymbolData(op.Symbol);

            symData.AddActiveOperation(op);
            if (this.Config.SaveData)
            {
                lock (DbLock)
                    DbActiveOperations.Upsert(op);
            }
        }
Exemple #2
0
        public async Task Update(TimeSlice slice)
        {
            LastUpdate = Market.Time;
            //update selected symbols
            var changes = await SymbolsFilter.UpdateAsync(slice);

            if (changes != SelectedSymbolsChanges.None)
            {
                var selectedForOperationsActive = this.ActiveOperations.Select(ao => ao.Symbol).GroupBy(ao => ao.Key).Select(g => g.First()).ToList();
                //release feeds of unused symbols
                foreach (var sym in changes.RemovedSymbols)
                {
                    SymbolData symbolData = GetSymbolData(sym);
                    symbolData.IsSelectedForTrading = false;
                    //if it doesn't have acrive operations
                    if (!selectedForOperationsActive.Any(aos => aos.Key == sym.Key))
                    {
                        if (symbolData.Feed != null)
                        {
                            symbolData.Feed.OnData -= Feed_OnData;
                            this.ReleaseFeed(symbolData.Feed);
                            symbolData.Feed = null;
                        }
                    }
                }

                //add feeds for added symbols and those that have open operations
                foreach (var sym in changes.AddedSymbols)
                {
                    SymbolData symbolData = GetSymbolData(sym);
                    symbolData.IsSelectedForTrading = true;
                }

                foreach (var sym in changes.AddedSymbols.Concat(selectedForOperationsActive))
                {
                    SymbolData symbolData = GetSymbolData(sym);
                    if (symbolData.Feed == null)
                    {
                        symbolData.Feed = await this.GetSymbolFeed(sym.Key);

                        symbolData.Feed.OnData -= Feed_OnData;
                        symbolData.Feed.OnData += Feed_OnData;
                    }
                }

                if (Sentry != null)
                {
                    await Sentry.OnSymbolsChanged(changes);
                }

                if (Allocator != null)
                {
                    Allocator.OnSymbolsChanged(changes);
                }

                if (Executor != null)
                {
                    Executor.OnSymbolsChanged(changes);
                }

                if (RiskManager != null)
                {
                    RiskManager.OnSymbolsChanged(changes);
                }
            }

            // register trades with their linked operations
            Operation[]      oldOperations     = null;
            List <Operation> operationsResumed = new List <Operation>();

            foreach (ITrade trade in slice.Trades)
            {
                //first search in active operations
                var symData  = _SymbolsData[trade.Symbol];
                var activeOp = symData.ActiveOperations.FirstOrDefault(op => op.IsTradeAssociated(trade));
                if (activeOp != null)
                {
                    if (activeOp.AddTrade(trade))
                    {
                        Logger.Info($"{Time} - New trade for operation {activeOp.ToString()}: {trade.ToString()}");
                    }
                }
                else
                {
                    //let's search in closed operations by getting ligtweigth instances
                    if (oldOperations == null)
                    {
                        //lock (DbLock)
                        //    oldOperations = oldOperations ?? DbClosedOperations.Find(o => o.CreationTime >= Market.Time.AddDays(-5)).ToArray();
                        lock (DbLock)
                            oldOperations = QueryClosedOperations(doc => doc["CreationTime"].AsDateTime >= Market.Time.AddDays(-4));
                    }

                    var oldOp = oldOperations.FirstOrDefault(op => op.IsTradeAssociated(trade));
                    //if we found an operation let's get a real instance
                    if (oldOp != null)
                    {
                        oldOp = DbClosedOperations.FindById(oldOp.Id);
                        if (oldOp == null)
                        {
                            Logger.Error($"Operation found then not found!  {oldOp}.");
                        }
                    }

                    if (oldOp != null)
                    {
                        operationsResumed.Add(oldOp);
                        if (oldOp.AddTrade(trade))
                        {
                            Logger.Info($"{Time} - New trade for 'old' operation {activeOp}: {trade.ToString()}");
                        }
                        //check if it got resumed by this new trade
                        if (!oldOp.IsClosed)
                        {
                            this.ResumeOperation(oldOp);
                            Logger.Info($"Resuming 'old' operation {activeOp}.");
                        }
                        else
                        {
                            oldOp.Dispose(); //otherwise we must dispose it
                        }
                    }
                    else
                    {
                        Logger.Debug($"{Time} - New trade {trade.ToString()} without any associated operation");
                    }
                }
            }
            //dispose the operations that we didn't use
            if (oldOperations != null)
            {
                foreach (var oper in oldOperations.Where(oo => !operationsResumed.Contains(oo)))
                {
                    oper.Dispose();
                }
            }

            // call OnUpdate
            await OnUpdate(slice);

            // get signals
            if (Sentry != null)
            {
                Sentry.UpdateAsync(slice);
            }

            //create operations
            if (Allocator != null)
            {
                Allocator.Update(slice);
            }

            //close operations that have been in close queue for enough time
            lock (DbLock)
            {
                this.Db?.BeginTrans();
                List <Operation> operationsToClose = _ActiveOperations.Where(op => this.Time >= op.CloseDeadTime).ToList();
                foreach (var op in operationsToClose)
                {
                    if (op.AmountInvested > 0)
                    {
                        Logger.Info("{0} - Closing operation {1}.", Time, op.ToString("c"));
                    }
                    else
                    {
                        Logger.Debug("{0} - Closing operation {1}.", Time, op.ToString("c"));
                    }
                    op.Close();
                    _ActiveOperations.Remove(op);
                    if (this.Config.SaveData || op.AmountInvested > 0)
                    {
                        this._ClosedOperations.Add(op);
                    }
                    this.SymbolsData[op.Symbol.Key].CloseOperation(op);

                    if (this.Config.SaveData)
                    {
                        lock (DbLock)
                        {
                            //update database
                            DbActiveOperations.Delete(op.Id);
                            DbClosedOperations.Upsert(op);
                        }
                    }
                }
                this.Db?.Commit();
            }

            //add new operations that have been created
            foreach (var op in slice.NewOperations)
            {
                AddActiveOperation(op);
            }

            //manage orders
            if (Executor != null)
            {
                await Executor.Update(slice);
            }

            //manage risk
            if (RiskManager != null)
            {
                await RiskManager.Update(slice);
            }

            while (Commands.Count > 0)
            {
                try
                {
                    if (Commands.TryDequeue(out Command command))
                    {
                        await command.Run();
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error($"Error while running command: {ex.Message}.");
                }
            }

            if (Config.SaveData)
            {
                SaveNonVolatileVars();
            }
        }