Beispiel #1
0
        async Task ReloadDbDataIfChangedImpl()   // if necessary it reloads Historical and Realtime data
        {
            Console.WriteLine("*MemDb is not yet ready! ReloadDbData is in progress...");
            DateTime startTime = DateTime.UtcNow;

            // GA.IM.NAV assets have user_id data, so User data has to be reloaded too before Assets
            (bool isDbReloadNeeded, User[]? newUsers, List <Asset>?sqCoreAssets) = m_Db.GetDataIfReloadNeeded();
            if (!isDbReloadNeeded)
            {
                return;
            }

            // to minimize the time memDb is not consintent we create everything into new pointers first, then update them quickly
            var newAssetCache = AssetsCache.CreateAssetCache(sqCoreAssets !);

            // var newPortfolios = GeneratePortfolios();

            if (IsInitialized)
            {
                // if this is the periodic (not initial) reload of RedisDb, then we don't surprise clients by emptying HistPrices
                // and not having HistPrices for 20minutes. So, we download HistPrices before swapping m_memData pointer
                DateTime startTimeHist = DateTime.UtcNow;
                var      newDailyHist  = await CreateDailyHist(m_Db, newUsers !, newAssetCache); // downloads historical prices from YF. Assume it takes 20min

                if (newDailyHist == null)
                {
                    newDailyHist = new CompactFinTimeSeries <DateOnly, uint, float, uint>();
                }
                m_lastHistoricalDataReload   = DateTime.UtcNow;
                m_lastHistoricalDataReloadTs = DateTime.UtcNow - startTimeHist;

                var newMemData = new MemData(newUsers !, newAssetCache, newDailyHist);
                m_memData = newMemData; // swap pointer in atomic operation
                Console.WriteLine($"*MemDb is ready! (#Assets: {AssetsCache.Assets.Count}, #HistoricalAssets: {DailyHist.GetDataDirect().Data.Count}) in {m_lastHistoricalDataReloadTs.TotalSeconds:0.000}sec");
            }
            else
            {
                // if this is the first time to load DB from Redis, then we don't demand HistData. Assume HistData crawling takes 20min
                // many clients can survive without historical data first. MarketDashboard. However, they need Asset and User data immediately.
                // BrAccInfo is fine wihout historical. It will send NaN as a LastClose. Fine. Client will handle it.
                // So, we don't need to wait for Historical to finish InitDb (that might take 20 minutes in the future).
                // !!! Also, in development, we don't want to wait until All HistData arrives, but start Debugging code right away after starting the WebServer.
                // Clients of MemDb should handle properly if HistData is not yet ready (NaN and later Refresh).
                var newMemData = new MemData(newUsers !, newAssetCache, new CompactFinTimeSeries <DateOnly, uint, float, uint>());
                m_memData = newMemData; // swap pointer in atomic operation
                Console.WriteLine($"*MemDb is half-ready! (#Assets: {AssetsCache.Assets.Count}, #HistoricalAssets: 0)");
            }

            m_lastDbReload   = DateTime.UtcNow;
            m_lastDbReloadTs = DateTime.UtcNow - startTime;

            foreach (var brAccount in BrAccounts)
            {
                UpdateBrAccPosAssetIds(brAccount.AccPoss);
            }

            OnReloadAssetData_ReloadRtDataAndSetTimer();    // downloads realtime prices from YF or IEX
            OnReloadAssetData_ReloadRtNavDataAndSetTimer(); // downloads realtime NAVs from VBrokers
            EvDbDataReloaded?.Invoke();
        }
Beispiel #2
0
        TsDateData <TKey, TAssetId, TValue1, TValue2> m_data;                                                          // this m_data pointer can be swapped in an atomic instruction after update

        static void HowToUseThisClassExamples()
        {
            DateOnly[] dates = new DateOnly[2] {
                new DateOnly(2020, 05, 05), new DateOnly(2020, 05, 06)
            };
            var dict1 = new Dictionary <TickType, float[]>()
            {
                { TickType.SplitDivAdjClose, new float[2] {
                      10.1f, 12.1f
                  } }
            };
            var  dict2   = new Dictionary <TickType, uint[]>();
            uint assetId = 1;
            var  data    = new Dictionary <uint, Tuple <Dictionary <TickType, float[]>, Dictionary <TickType, uint[]> > >()
            {
                { assetId, new Tuple <Dictionary <TickType, float[]>, Dictionary <TickType, uint[]> >(dict1, dict2) }
            };

            var ts1 = new CompactFinTimeSeries <DateOnly, uint, float, uint>();

            ts1.ChangeData(dates, data);
        }
Beispiel #3
0
 public MemData(User[] newUsers, AssetsCache newAssetCache, CompactFinTimeSeries <DateOnly, uint, float, uint> newDailyHist)
 {
     Users       = newUsers;
     AssetsCache = newAssetCache;
     DailyHist   = newDailyHist;
 }