예제 #1
0
        public void LoadNonVolatileVars()
        {
            lock (DbLock)
            {
                //reload my internal state
                BsonDocument states = Db.GetCollection("State").FindById("TradingAlgoState");
                if (states != null)
                {
                    State = Db.Mapper.Deserialize <NonVolatileVars>(states["State"]);

                    //reload derived class state
                    this.RestoreState(Db.Mapper.Deserialize <object>(states["DerivedClassState"]));

                    //reload modules state
                    Sentry.RestoreState(Db.Mapper.Deserialize <object>(states["Sentry"]));
                    Allocator.RestoreState(Db.Mapper.Deserialize <object>(states["Allocator"]));
                    Executor.RestoreState(Db.Mapper.Deserialize <object>(states["Executor"]));
                    RiskManager.RestoreState(Db.Mapper.Deserialize <object>(states["RiskManager"]));
                }



                //rebuild symbols data
                foreach (var symData in Db.GetCollection <SymbolData>("SymbolsData").FindAll())
                {
                    _SymbolsData[symData.Id] = symData;
                }

                if (Db.UserVersion < 4)
                {
                    foreach (var op in DbClosedOperations.FindAll().ToArray())
                    {
                        op.Recalculate();
                        DbClosedOperations.Upsert(op);
                    }

                    foreach (var op in DbActiveOperations.FindAll().ToArray())
                    {
                        op.Recalculate();
                        DbActiveOperations.Upsert(op);
                    }

                    Db.UserVersion = 4;
                    Db.Checkpoint();
                    Db.Rebuild();
                }

                //rebuild operations
                //closed operations are not loaded in current session
                foreach (var op in DbActiveOperations.FindAll().ToArray())
                {
                    this.AddActiveOperation(op);
                }
            }
        }
예제 #2
0
        public void SaveNonVolatileVars()
        {
            lock (DbLock)
            {
                //save my internal state
                BsonDocument state = new BsonDocument();
                state["_id"]   = "TradingAlgoState";
                state["State"] = Db.Mapper.Serialize(State);

                //Save derived state
                state["DerivedClassState"] = Db.Mapper.Serialize(GetState());

                //save module states
                state["Sentry"]      = Db.Mapper.Serialize(Sentry.GetState());
                state["Allocator"]   = Db.Mapper.Serialize(Allocator.GetState());
                state["Executor"]    = Db.Mapper.Serialize(Executor.GetState());
                state["RiskManager"] = Db.Mapper.Serialize(RiskManager.GetState());

                Db.GetCollection("State").Upsert(state);

                foreach (var symData in SymbolsData.Values)
                {
                    Db.GetCollection <SymbolData>("SymbolsData").Upsert(symData);
                }

                Db.BeginTrans();
                foreach (var op in ActiveOperations.Where(op => op.IsChanged))
                {
                    DbActiveOperations.Upsert(op);
                }
                foreach (var op in ClosedOperations.Where(op => op.IsChanged))
                {
                    DbClosedOperations.Upsert(op);
                }
                Db.Commit();

                Db.Checkpoint();
            }
        }
예제 #3
0
        public override async Task OnStartAsync()
        {
            await this.Initialize();

            await SymbolsFilter.Initialize(this);

            if (Sentry != null)
            {
                await Sentry.Initialize(this);
            }
            if (Allocator != null)
            {
                await Allocator.Initialize(this);
            }
            if (Executor != null)
            {
                await Executor.Initialize(this);
            }
            if (RiskManager != null)
            {
                await RiskManager.Initialize(this);
            }
        }
예제 #4
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();
            }
        }