public async Task EvaluateRateAsync(Currency from, Currency to)
        {
            var now = DateTime.UtcNow;

            if (now.DayOfWeek == DayOfWeek.Saturday || now.DayOfWeek == DayOfWeek.Sunday)
            {
                return;
            }

            var rate = await _rateFatcher.GetRateAsync(from, to);

            var reversedRate = 1f / rate;

            _logger.LogInformation($"Evaluating {from} -> {to} with: {rate} [{reversedRate}]");

            var closeOportunities = await FindCloseOportunitiesAsync(from, to, rate);

            _logger.LogInformation($"Found opportunities for {from} -> {to}: {string.Join(",", closeOportunities.Select(p => p.Id))}");

            var reverseOpportunities = await FindCloseOportunitiesAsync(to, from, reversedRate);

            _logger.LogInformation($"Found opportunities for {to} -> {from}: {string.Join(",", reverseOpportunities.Select(p => p.Id))}");
            closeOportunities.AddRange(reverseOpportunities);

            var notification = string.Join("<br>", closeOportunities.Select(p => $"<a href=\"{_options.CloseUIUrl}id={p.Id}\">[{p.Id}]</a> {p.FromCurrency} -> {p.ToCurrency} : {p.OpenAmount} for {p.OpenRate}. Proposal: {p.OpenAmount*p.OpenRate} [{rate} - {reversedRate}]"));

            if (!string.IsNullOrEmpty(notification))
            {
                NotificationManager.Notify("Opportunities", notification, NotificationTarget);
            }

            if (now.Hour == _options.OpenHour)
            {
                var reversedAmount = _options.OpenAmount / reversedRate;
                var openedId       = await _dataStore.Position.OpenAsync(from.ToString(), to.ToString(), _options.OpenAmount, rate);

                var reverseOpenedId = await _dataStore.Position.OpenAsync(to.ToString(), from.ToString(), reversedAmount, reversedRate);

                _logger.LogInformation($"Opened: {from} -> {to} for {rate}");
                _logger.LogInformation($"Opened: {to} -> {from} for {reversedRate}");

                NotificationManager.Notify("Opened", $"[{openedId}/{reverseOpenedId}] {from} -> {to} : {rate} [{reversedRate}]", NotificationTarget);
            }
        }
Example #2
0
        public async Task OffsetIsDynamicalyComputed()
        {
            _rateFetcher.GetRateAsync(Currency.EUR, Currency.USD).Returns(Task.FromResult(1.195f));
            _position.FindOpenPositionsAsync(Arg.Any <string>(), Arg.Any <string>(), Arg.Any <float>()).Returns(Task.FromResult(new List <Position>()));

            float offsetOfReverted = float.NaN;
            float offset           = float.NaN;

            await _position.FindOpenPositionsAsync("EUR", "USD", Arg.Do <float>(a => offset = a));

            await _position.FindOpenPositionsAsync("USD", "EUR", Arg.Do <float>(a => offsetOfReverted = a));

            await _underTest.EvaluateRateAsync(Currency.EUR, Currency.USD);

            offset.Should().NotBe(float.NaN, "offset needs to be evaluated");
            // this is needed because of precision (1.195f + 0.003f = 1.1980000007)
            offset.Should().BeInRange(1.198f, 1.19811f, "offset is equal to configured one");

            offsetOfReverted.Should().NotBe(float.NaN, "reverted offset needs to be evaluated");
            offsetOfReverted.Should().BeInRange(0.8369f, 0.8398f, "reverted offset is less than non-reverted");
        }
Example #3
0
        public void Setup()
        {
            _options = new RateEvaluatorOptions
            {
                CloseOffsetPercentage = 0.26f,
                NotificationTarget    = TargetEmail,
                OpenAmount            = 10,
                OpenHour = DateTime.UtcNow.Hour
            };
            var logger = Substitute.For <ILogger <DefaultRateEvaluator> >();

            _notificationManager = Substitute.For <INotificationManager>();
            _rateFetcher         = Substitute.For <IRates>();
            _rateFetcher.GetRateAsync(Currency.EUR, Currency.USD).Returns(Task.FromResult(2f));

            _position = Substitute.For <IPosition>();

            var store = Substitute.For <IDataStore>();

            store.Position.Returns(_position);

            _underTest = new DefaultRateEvaluator(_options, logger, _notificationManager, _rateFetcher, store);
        }