public void ThrowingEnumeratorStackDisposesOfSubscription() { var enumerator = new TestDataEnumerator { MoveNextTrueCount = 10, ThrowException = true }; var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator); var count = 0; while (enumerator.MoveNextTrueCount != 9) { if (count++ > 100) { Assert.Fail("Timeout waiting for producer"); } Thread.Sleep(1); } Assert.IsFalse(subscription.MoveNext()); Assert.IsTrue(subscription.EndOfStream); Assert.IsTrue(enumerator.Disposed); }
public async Task <ActionResult <object> > GetUserSubscriptions([FromRoute] string platformId, [FromRoute] string subscriptionName = null) { if (string.IsNullOrEmpty(platformId)) { throw new ArgumentException("platformId"); } try { var id = BitcornUtils.GetPlatformId(platformId); var user = await BitcornUtils.GetUserForPlatform(id, _dbContext).FirstOrDefaultAsync(); if (user != null) { var now = DateTime.Now; var subscriptionsQuery = SubscriptionUtils.GetUserSubscriptions(_dbContext, user) .Join(_dbContext.Subscription, (UserSubcriptionTierInfo info) => info.SubscriptionTier.SubscriptionId, (Subscription sub) => sub.SubscriptionId, (info, sub) => new { userInfo = info, subscriptionInfo = sub }).Where(s => s.userInfo.UserSubscription.LastSubDate.Value.AddDays(s.subscriptionInfo.Duration) > now); if (string.IsNullOrEmpty(subscriptionName) || subscriptionName == "*") { return(await subscriptionsQuery.Select(s => new { daysLeft = (s.userInfo.UserSubscription.LastSubDate.Value.AddDays(s.subscriptionInfo.Duration) - now).TotalDays, tier = s.userInfo.SubscriptionTier.Tier, name = s.subscriptionInfo.Name, description = s.subscriptionInfo.Description, lastSubDate = s.userInfo.UserSubscription.LastSubDate }).ToArrayAsync()); } else { return(await subscriptionsQuery.Where(q => q.subscriptionInfo.Name.ToLower() == subscriptionName.ToLower()).Select(s => new { daysLeft = (s.userInfo.UserSubscription.LastSubDate.Value.AddDays(s.subscriptionInfo.Duration) - now).TotalDays, tier = s.userInfo.SubscriptionTier.Tier, name = s.subscriptionInfo.Name, description = s.subscriptionInfo.Description, lastSubDate = s.userInfo.UserSubscription.LastSubDate }).ToArrayAsync()); } } else { return(StatusCode(404)); } } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e, JsonConvert.SerializeObject(new { platformId, subscriptionName })); throw e; } }
// This unit tests reproduces GH 3885 where the consumer hanged forever public void ConsumerDoesNotHang() { for (var i = 0; i < 10000; i++) { var dataPoints = 10; var enumerator = new TestDataEnumerator { MoveNextTrueCount = dataPoints }; var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator); for (var j = 0; j < dataPoints; j++) { Assert.IsTrue(subscription.MoveNext()); } Assert.IsFalse(subscription.MoveNext()); subscription.DisposeSafely(); } }
public async Task TestSubscriptionTierCheck() { var dbContext = TestUtils.CreateDatabase(); try { var testName = "test"; var testId = "auth0|test"; TestUtils.TryRemoveTestUser(testId); TestUtils.CreateTestUser(testName, testId); var user = dbContext.JoinUserModels().FirstOrDefault(u => u.UserIdentity.Auth0Id == testId); user.UserWallet.Balance += 10000001; dbContext.SaveChanges(); var resp = await SubscriptionUtils.Subscribe(dbContext, user, new SubRequest() { SubscriptionName = "BITCORNFarms", Tier = 1, Platform = "test", Amount = 100000 }); Assert.False(await SubscriptionUtils.HasSubscribed(dbContext, user, "BITCORNFarms", 2)); } finally { dbContext.Dispose(); } }
// This unit tests reproduces GH 3885 where the consumer hanged forever public void ConsumerDoesNotHang() { for (var i = 0; i < 10000; i++) { var dataPoints = 10; var enumerator = new TestDataEnumerator { MoveNextTrueCount = dataPoints }; var factorFileProfider = new Mock <IFactorFileProvider>(); factorFileProfider.Setup(s => s.Get(It.IsAny <Symbol>())).Returns(FactorFile.Read(_security.Symbol.Value, _config.Market)); var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator, factorFileProfider.Object, false); for (var j = 0; j < dataPoints; j++) { Assert.IsTrue(subscription.MoveNext()); } Assert.IsFalse(subscription.MoveNext()); subscription.DisposeSafely(); } }
public async Task <ActionResult <SubscriptionResponse> > New([FromBody] SubRequest subRequest) { var platformId = BitcornUtils.GetPlatformId(subRequest.Id); var user = await BitcornUtils.GetUserForPlatform(platformId, _dbContext).FirstOrDefaultAsync(); if (user != null && UserLockCollection.Lock(user.UserId)) { try { subRequest.Platform = platformId.Platform; var tx = await SubscriptionUtils.Subscribe(_dbContext, user, subRequest); if (tx != null) { return(tx); } } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e, JsonConvert.SerializeObject(subRequest)); throw e; } finally { UserLockCollection.Release(user.UserId); } } return(StatusCode((int)HttpStatusCode.BadRequest)); }
public void SubscriptionIsDisposed() { var dataPoints = 10; var enumerator = new TestDataEnumerator { MoveNextTrueCount = dataPoints }; var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator); var count = 0; while (enumerator.MoveNextTrueCount > 8) { if (count++ > 100) { Assert.Fail($"Timeout waiting for producer. {enumerator.MoveNextTrueCount}"); } Thread.Sleep(1); } subscription.DisposeSafely(); Assert.IsFalse(subscription.MoveNext()); }
/// <summary> /// Creates a new <see cref="AuxiliaryDataEnumerator"/> that will hold the /// corporate event providers /// </summary> /// <param name="rawDataEnumerator">The underlying raw data enumerator</param> /// <param name="config">The <see cref="SubscriptionDataConfig"/></param> /// <param name="factorFileProvider">Used for getting factor files</param> /// <param name="tradableDayNotifier">Tradable dates provider</param> /// <param name="mapFileResolver">Used for resolving the correct map files</param> /// <param name="includeAuxiliaryData">True to emit auxiliary data</param> /// <param name="startTime">Start date for the data request</param> /// <param name="enablePriceScaling">Applies price factor</param> /// <returns>The new auxiliary data enumerator</returns> public static IEnumerator <BaseData> CreateEnumerators( IEnumerator <BaseData> rawDataEnumerator, SubscriptionDataConfig config, IFactorFileProvider factorFileProvider, ITradableDatesNotifier tradableDayNotifier, MapFileResolver mapFileResolver, bool includeAuxiliaryData, DateTime startTime, bool enablePriceScaling = true) { var lazyFactorFile = new Lazy <FactorFile>(() => SubscriptionUtils.GetFactorFileToUse(config, factorFileProvider)); var tradableEventProviders = new List <ITradableDateEventProvider>(); if (config.Symbol.SecurityType == SecurityType.Equity) { tradableEventProviders.Add(new SplitEventProvider()); tradableEventProviders.Add(new DividendEventProvider()); } if (config.Symbol.SecurityType == SecurityType.Equity || config.Symbol.SecurityType == SecurityType.Base || config.Symbol.SecurityType == SecurityType.Option) { tradableEventProviders.Add(new MappingEventProvider()); } tradableEventProviders.Add(new DelistingEventProvider()); var enumerator = new AuxiliaryDataEnumerator( config, lazyFactorFile, new Lazy <MapFile>(() => GetMapFileToUse(config, mapFileResolver)), tradableEventProviders.ToArray(), tradableDayNotifier, includeAuxiliaryData, startTime); // avoid price scaling for backtesting; calculate it directly in worker // and allow subscription to extract the the data depending on config data mode var dataEnumerator = rawDataEnumerator; if (enablePriceScaling) { dataEnumerator = new PriceScaleFactorEnumerator( rawDataEnumerator, config, lazyFactorFile); } return(new SynchronizingEnumerator(dataEnumerator, enumerator)); }
public void PriceScaleDoesNotUpdateForFillForwardBar() { var referenceTime = new DateTime(2020, 08, 06); var point = new Tick(referenceTime, Symbols.SPY, 1, 2); var point2 = point.Clone(true); point2.Time = referenceTime.AddDays(1); var point3 = point.Clone(false); point3.Time = referenceTime.AddDays(2); ; var enumerator = new List <BaseData> { point, point2, point3 }.GetEnumerator(); var factorFileProfider = new Mock <IFactorFileProvider>(); var factorFile = new FactorFile(_security.Symbol.Value, new[] { new FactorFileRow(referenceTime, 0.5m, 1), new FactorFileRow(referenceTime.AddDays(1), 1m, 1) }, referenceTime); factorFileProfider.Setup(s => s.Get(It.IsAny <Symbol>())).Returns(factorFile); var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, referenceTime, Time.EndOfTime ), enumerator, factorFileProfider.Object, true); Assert.IsTrue(subscription.MoveNext()); Assert.AreEqual(1, (subscription.Current.Data as Tick).AskPrice); Assert.IsFalse((subscription.Current.Data as Tick).IsFillForward); Assert.IsTrue(subscription.MoveNext()); Assert.AreEqual(1, (subscription.Current.Data as Tick).AskPrice); Assert.IsTrue((subscription.Current.Data as Tick).IsFillForward); Assert.IsTrue(subscription.MoveNext()); Assert.AreEqual(2, (subscription.Current.Data as Tick).AskPrice); Assert.IsFalse((subscription.Current.Data as Tick).IsFillForward); subscription.DisposeSafely(); }
/// <summary> /// Creates a subscription to process the history request /// </summary> protected Subscription CreateSubscription(HistoryRequest request, IEnumerable <BaseData> history) { var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var reader = history.GetEnumerator(); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // FillForwardEnumerator expects these values in local times var start = request.StartTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var end = request.EndTimeUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, request.IncludeExtendedMarketHours, end, config.Increment, config.DataTimeZone); } var subscriptionRequest = new SubscriptionRequest(false, null, security, config, request.StartTimeUtc, request.EndTimeUtc); return(SubscriptionUtils.Create(subscriptionRequest, reader)); }
public void SubscriptionEmitsAuxData(Type typeOfConfig, bool shouldReceiveAuxData) { var factorFileProvider = new Mock <IFactorFileProvider>(); var config = new SubscriptionDataConfig(typeOfConfig, _security.Symbol, Resolution.Hour, TimeZones.NewYork, TimeZones.NewYork, true, true, false); factorFileProvider.Setup(s => s.Get(It.IsAny <Symbol>())).Returns(FactorFile.Read(_security.Symbol.Value, config.Market)); var totalPoints = 8; var time = new DateTime(2010, 1, 1); var enumerator = Enumerable.Range(0, totalPoints).Select(x => new Delisting { Time = time.AddHours(x) }).GetEnumerator(); var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, config, DateTime.UtcNow, Time.EndOfTime ), enumerator, factorFileProvider.Object, false); // Test our subscription stream to see if it emits the aux data it should be filtered // by the SubscriptionUtils produce function if the config isn't for a TradeBar int dataReceivedCount = 0; while (subscription.MoveNext()) { dataReceivedCount++; if (subscription.Current != null && subscription.Current.Data.DataType == MarketDataType.Auxiliary) { Assert.IsTrue(shouldReceiveAuxData); } } // If it should receive aux data it should have emitted all points // otherwise none should have been emitted if (shouldReceiveAuxData) { Assert.AreEqual(totalPoints, dataReceivedCount); } else { Assert.AreEqual(0, dataReceivedCount); } }
public void ThrowingEnumeratorStackDisposesOfSubscription() { var enumerator = new TestDataEnumerator { MoveNextTrueCount = 10, ThrowException = true }; var factorFileProfider = new Mock <IFactorFileProvider>(); factorFileProfider.Setup(s => s.Get(It.IsAny <Symbol>())).Returns(FactorFile.Read(_security.Symbol.Value, _config.Market)); var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator, factorFileProfider.Object, false); var count = 0; while (enumerator.MoveNextTrueCount != 9) { if (count++ > 100) { Assert.Fail("Timeout waiting for producer"); } Thread.Sleep(1); } Assert.IsFalse(subscription.MoveNext()); Assert.IsTrue(subscription.EndOfStream); // enumerator is disposed by the producer count = 0; while (!enumerator.Disposed) { if (count++ > 100) { Assert.Fail("Timeout waiting for producer"); } Thread.Sleep(1); } }
public async Task <ActionResult <bool> > IsSubbed([FromRoute] string platformId, [FromRoute] string subscriptionName, [FromQuery] string subTier = null) { if (string.IsNullOrEmpty(platformId)) { throw new ArgumentException("platformId"); } if (string.IsNullOrEmpty(subscriptionName)) { throw new ArgumentException("subscriptionName"); } try { var id = BitcornUtils.GetPlatformId(platformId); var user = await BitcornUtils.GetUserForPlatform(id, _dbContext).FirstOrDefaultAsync(); if (user != null) { int?tier = null; if (!string.IsNullOrEmpty(subTier)) { try { tier = int.Parse(subTier); } catch { } } return(await SubscriptionUtils.HasSubscribed(_dbContext, user, subscriptionName, tier)); } else { return(StatusCode(404)); } } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e, JsonConvert.SerializeObject(new { subTier, platformId, subscriptionName })); throw e; } }
public void FirstLoopLimit(int firstLoopLimit) { var dataPoints = 10; var enumerator = new TestDataEnumerator { MoveNextTrueCount = dataPoints }; var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator, firstLoopLimit: firstLoopLimit); var count = 0; var expectedValue = dataPoints - firstLoopLimit - 1; expectedValue = expectedValue > 0 ? expectedValue : -1; while (enumerator.MoveNextTrueCount != expectedValue) { if (count++ > 100) { Assert.Fail("Timeout waiting for producer"); } Thread.Sleep(1); } // producer should only have produced 'firstLoopLimit' data points, lets assert remaining to produce Assert.AreEqual(expectedValue, enumerator.MoveNextTrueCount); for (var j = 0; j < dataPoints; j++) { Assert.IsTrue(subscription.MoveNext()); } Assert.IsFalse(subscription.MoveNext()); subscription.DisposeSafely(); Assert.IsTrue(enumerator.Disposed); }
public async Task TestNotSubbedCheck() { var dbContext = TestUtils.CreateDatabase(); try { var testName = "test"; var testId = "auth0|test"; TestUtils.TryRemoveTestUser(testId); TestUtils.CreateTestUser(testName, testId); var user = dbContext.JoinUserModels().FirstOrDefault(u => u.UserIdentity.Auth0Id == testId); Assert.False(await SubscriptionUtils.HasSubscribed(dbContext, user, "BITCORNFarms", 1)); } finally { dbContext.Dispose(); } }
public void FundEntity_DataCorrect_EntityFunded() { var user = UserFaker.Create(); var amount = Rand.SmallDecimal(); var balance = UserBalanceRepository.FindOrCreate(user, CurrencyType.BitCoin); balance.UpdateBalance(amount); var info = UserSubscriptionInfoRepository.FindOrCreate(user); info.UpdateSelectedAmount(amount).Refresh(); ProjectFaker.Create(); SubscriptionUtils.PeriodPay(user); var txs = FundingTransactionRepository.Get(user); Assert.True(txs.Length > 0); Assert.True(txs[0].amount > 0); }
public void SubscriptionIsDisposed() { var dataPoints = 10; var enumerator = new TestDataEnumerator { MoveNextTrueCount = dataPoints }; var factorFileProfider = new Mock <IFactorFileProvider>(); factorFileProfider.Setup(s => s.Get(It.IsAny <Symbol>())).Returns(FactorFile.Read(_security.Symbol.Value, _config.Market)); var subscription = SubscriptionUtils.CreateAndScheduleWorker( new SubscriptionRequest( false, null, _security, _config, DateTime.UtcNow, Time.EndOfTime ), enumerator, factorFileProfider.Object, false); var count = 0; while (enumerator.MoveNextTrueCount > 8) { if (count++ > 100) { Assert.Fail($"Timeout waiting for producer. {enumerator.MoveNextTrueCount}"); } Thread.Sleep(1); } subscription.DisposeSafely(); Assert.IsFalse(subscription.MoveNext()); }
/// <summary> /// Creates a subscription to process the request /// </summary> private Subscription CreateSubscription(HistoryRequest request, DateTime startUtc, DateTime endUtc) { // data reader expects these values in local times var startTimeLocal = startUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var endTimeLocal = endUtc.ConvertFromUtc(request.ExchangeHours.TimeZone); var config = new SubscriptionDataConfig(request.DataType, request.Symbol, request.Resolution, request.DataTimeZone, request.ExchangeHours.TimeZone, request.FillForwardResolution.HasValue, request.IncludeExtendedMarketHours, false, request.IsCustomData, request.TickType, true, request.DataNormalizationMode ); _dataPermissionManager.AssertConfiguration(config); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var mapFileResolver = MapFileResolver.Empty; if (config.TickerShouldBeMapped()) { mapFileResolver = _mapFileProvider.Get(config.Market); var mapFile = mapFileResolver.ResolveMapFile(config.Symbol.ID.Symbol, config.Symbol.ID.Date); config.MappedSymbol = mapFile.GetMappedSymbol(startTimeLocal, config.MappedSymbol); } // Tradable dates are defined with the data time zone to access the right source var tradableDates = Time.EachTradeableDayInTimeZone(request.ExchangeHours, startTimeLocal, endTimeLocal, request.DataTimeZone, request.IncludeExtendedMarketHours); var dataReader = new SubscriptionDataReader(config, startTimeLocal, endTimeLocal, mapFileResolver, _factorFileProvider, tradableDates, false, _dataCacheProvider ); dataReader.InvalidConfigurationDetected += (sender, args) => { OnInvalidConfigurationDetected(args); }; dataReader.NumericalPrecisionLimited += (sender, args) => { OnNumericalPrecisionLimited(args); }; dataReader.StartDateLimited += (sender, args) => { OnStartDateLimited(args); }; dataReader.DownloadFailed += (sender, args) => { OnDownloadFailed(args); }; dataReader.ReaderErrorDetected += (sender, args) => { OnReaderErrorDetected(args); }; IEnumerator <BaseData> reader = dataReader; var intraday = GetIntradayDataEnumerator(dataReader, request); if (intraday != null) { // we optionally concatenate the intraday data enumerator reader = new ConcatEnumerator(true, reader, intraday); } reader = CorporateEventEnumeratorFactory.CreateEnumerators( reader, config, _factorFileProvider, dataReader, mapFileResolver, false, startTimeLocal); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, request.IncludeExtendedMarketHours, endTimeLocal, config.Increment, config.DataTimeZone, startTimeLocal); } // since the SubscriptionDataReader performs an any overlap condition on the trade bar's entire // range (time->end time) we can end up passing the incorrect data (too far past, possibly future), // so to combat this we deliberately filter the results from the data reader to fix these cases // which only apply to non-tick data reader = new SubscriptionFilterEnumerator(reader, security, endTimeLocal, config.ExtendedMarketHours, false); reader = new FilterEnumerator <BaseData>(reader, data => { // allow all ticks if (config.Resolution == Resolution.Tick) { return(true); } // filter out future data if (data.EndTime > endTimeLocal) { return(false); } // filter out data before the start return(data.EndTime > startTimeLocal); }); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, request.StartTimeUtc, request.EndTimeUtc); if (_parallelHistoryRequestsEnabled) { return(SubscriptionUtils.CreateAndScheduleWorker(subscriptionRequest, reader, _factorFileProvider, false)); } return(SubscriptionUtils.Create(subscriptionRequest, reader)); }
/// <summary> /// Creates a subscription to process the request /// </summary> private Subscription CreateSubscription(HistoryRequest request) { var config = request.ToSubscriptionDataConfig(); DataPermissionManager.AssertConfiguration(config, request.StartTimeLocal, request.EndTimeLocal); var security = new Security( request.ExchangeHours, config, new Cash(Currencies.NullCurrency, 0, 1m), SymbolProperties.GetDefault(Currencies.NullCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ); var dataReader = new SubscriptionDataReader(config, request, _mapFileProvider, _factorFileProvider, _dataCacheProvider, _dataProvider ); dataReader.InvalidConfigurationDetected += (sender, args) => { OnInvalidConfigurationDetected(args); }; dataReader.NumericalPrecisionLimited += (sender, args) => { OnNumericalPrecisionLimited(args); }; dataReader.StartDateLimited += (sender, args) => { OnStartDateLimited(args); }; dataReader.DownloadFailed += (sender, args) => { OnDownloadFailed(args); }; dataReader.ReaderErrorDetected += (sender, args) => { OnReaderErrorDetected(args); }; IEnumerator <BaseData> reader = dataReader; var intraday = GetIntradayDataEnumerator(dataReader, request); if (intraday != null) { // we optionally concatenate the intraday data enumerator reader = new ConcatEnumerator(true, reader, intraday); } reader = CorporateEventEnumeratorFactory.CreateEnumerators( reader, config, _factorFileProvider, dataReader, _mapFileProvider, request.StartTimeLocal); // optionally apply fill forward behavior if (request.FillForwardResolution.HasValue) { // copy forward Bid/Ask bars for QuoteBars if (request.DataType == typeof(QuoteBar)) { reader = new QuoteBarFillForwardEnumerator(reader); } var readOnlyRef = Ref.CreateReadOnly(() => request.FillForwardResolution.Value.ToTimeSpan()); reader = new FillForwardEnumerator(reader, security.Exchange, readOnlyRef, request.IncludeExtendedMarketHours, request.EndTimeLocal, config.Increment, config.DataTimeZone); } // since the SubscriptionDataReader performs an any overlap condition on the trade bar's entire // range (time->end time) we can end up passing the incorrect data (too far past, possibly future), // so to combat this we deliberately filter the results from the data reader to fix these cases // which only apply to non-tick data reader = new SubscriptionFilterEnumerator(reader, security, request.EndTimeLocal, config.ExtendedMarketHours, false, request.ExchangeHours); reader = new FilterEnumerator <BaseData>(reader, data => { // allow all ticks if (config.Resolution == Resolution.Tick) { return(true); } // filter out all aux data if (data.DataType == MarketDataType.Auxiliary) { return(false); } // filter out future data if (data.EndTime > request.EndTimeLocal) { return(false); } // filter out data before the start return(data.EndTime > request.StartTimeLocal); }); var subscriptionRequest = new SubscriptionRequest(false, null, security, config, request.StartTimeUtc, request.EndTimeUtc); if (_parallelHistoryRequestsEnabled) { return(SubscriptionUtils.CreateAndScheduleWorker(subscriptionRequest, reader, _factorFileProvider, false)); } return(SubscriptionUtils.Create(subscriptionRequest, reader)); }
async Task RunFullReferralTest(bool sub, bool runSubFirst = true) { var testName = "test"; var testId = "auth0|test"; await TestUtils.RegisterNewUserWithReferralArgs(testName, testId, 2); await TestSyncPlatformWithReferralInternal(testName, testId, true, false, 2); var dbContext = TestUtils.CreateDatabase(); try { var user = dbContext.JoinUserModels().FirstOrDefault(u => u.UserIdentity.Auth0Id == testId); user.UserWallet.Balance += UserWalletController.MIN_BALANCE_QUEST_AMOUNT + 10000000; dbContext.SaveChanges(); var userWalletController = new UserWalletController(dbContext); await userWalletController.Wallet("twitch|1337"); if (sub && runSubFirst) { var resp = await SubscriptionUtils.Subscribe(dbContext, user, new SubRequest() { SubscriptionName = "BITCORNFarms", Tier = 1, Platform = "test", Amount = 100000 }); } await TestUtils.TestWalletDownloadWithReferrerInternal(dbContext, "1.1.1.1", user, sub&&runSubFirst); if (sub && !runSubFirst) { var resp = await SubscriptionUtils.Subscribe(dbContext, user, new SubRequest() { SubscriptionName = "BITCORNFarms", Tier = 1, Platform = "test", Amount = 100000 }); } var userReferral = dbContext.UserReferral.FirstOrDefault(u => u.UserId == user.UserId); Assert.True(userReferral.SignupReward != null); Assert.True(userReferral.MinimumBalanceDate != null); Assert.True(userReferral.WalletDownloadDate != null); Assert.True(userReferral.SyncDate != null); if (!sub) { Assert.True(userReferral.Bonus == null); Assert.True(userReferral.ReferrerBonus == null); Assert.True(userReferral.UserSubscriptionId == null); } else { Assert.True(userReferral.UserSubscriptionId != null); Assert.True(userReferral.Bonus != null); Assert.True(userReferral.ReferrerBonus != null); } } finally { dbContext.Dispose(); } }
public async Task <ActionResult <List <AvailableSubscriptionResponse> > > Available([FromRoute] string subscriptionName = null) { try { AvailableSubscriptionInfo[] subscriptions = null; var query = (from subscriptionTier in _dbContext.SubscriptionTier join subscription in _dbContext.Subscription on subscriptionTier.SubscriptionId equals subscription.SubscriptionId select new AvailableSubscriptionInfo { SubscriptionTier = subscriptionTier, Subscription = subscription }); if (string.IsNullOrEmpty(subscriptionName) || subscriptionName == "*") { subscriptions = await query.ToArrayAsync(); } else { subscriptions = await query.Where(s => s.Subscription.Name.ToLower() == subscriptionName.ToLower()).ToArrayAsync(); } var availableSubscriptions = new List <AvailableSubscriptionResponse>(); var cornUsdt = await ProbitApi.GetCornPriceAsync(_dbContext); foreach (var row in subscriptions) { var existingEntry = availableSubscriptions.FirstOrDefault(l => l.Subscription.SubscriptionId == row.Subscription.SubscriptionId); if (existingEntry == null) { existingEntry = new AvailableSubscriptionResponse() { Subscription = row.Subscription, }; availableSubscriptions.Add(existingEntry); } decimal actualCost = 0; if (row.SubscriptionTier.CostUsdt != null && row.SubscriptionTier.CostUsdt > 0) { actualCost = SubscriptionUtils.CalculateUsdtToCornCost(cornUsdt, row.SubscriptionTier); if (row.SubscriptionTier.CostCorn == 0 || row.SubscriptionTier.CostCorn == null) { row.SubscriptionTier.CostCorn = actualCost; } } else if (row.SubscriptionTier.CostCorn != null && row.SubscriptionTier.CostCorn > 0) { actualCost = row.SubscriptionTier.CostCorn.Value; } existingEntry.Tiers.Add(new { tierInfo = row.SubscriptionTier, actualCost }); } return(availableSubscriptions); } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e, subscriptionName); throw e; } }