Esempio n. 1
0
        private static async Task <TradeOpportunity> GetOrUpdateTradeOpportunity(Opportunity opportunity, bool IsSimulation)
        {
            // Update requirements and maximum possible trade.
            var requirements = opportunity.UpdateRequirementsAndAmount().ToList();

            //
            string stateCode = opportunity.RequirementsMet ? "RQ-MET" : "RQ-MISSING";

            decimal oppValue = opportunity.GetMarginValuePercent();

            // Create the trade value;
            var newTradeValue = new TradeOpportunityValue()
            {
                PotentialMargin         = oppValue,
                Timestamp               = DateTime.UtcNow,
                TradeOpportunityStateId = TradeOpportunityState.States.Single(x => x.Code == stateCode).Id
            };

            // If the oppvalue is below treshold and doesn't exist yet, then ignore it. Else stop it.
            if (oppValue < SystemSetting.MinimumTradeOpportunityPercent)
            {
                TradeOpportunity tradOpp = null;
                tradeOpportunities.TryGetValue(opportunity.UniqueIdentifier, out tradOpp);

                if (tradOpp == null)
                {
                    return(null);
                }
                else
                {
                    var belowThresholdState = TradeOpportunityState.States.Single(x => x.Code == "EXP-BELOW");
                    newTradeValue.TradeOpportunityStateId = belowThresholdState.Id;
                    await EndTradeOpportunity(tradOpp, belowThresholdState, newTradeValue);

                    return(null);
                }
            }


            // Try getting the TradeOpp from the dictionary. If it doesn't exist, then construct it now
            var isNewOpportunity = false;
            var tradeOpp         = tradeOpportunities.GetOrAdd(opportunity.UniqueIdentifier, (key) =>
            {
                isNewOpportunity = true;
                return(new TradeOpportunity()
                {
                    CurrencyId = opportunity.OpportunityBaseCurrency.Id,
                    IsExecuted = false,
                    IsSimulation = IsSimulation,
                    StartTime = DateTime.UtcNow,
                    TradeOpportunityTypeId = TradeOpportunityType.Types.Single(x => x.Code == opportunity.TypeCode).Id,
                    TradeOpportunityStateId = TradeOpportunityState.States.Single(x => x.Code == stateCode).Id,
                    Description = opportunity.UniqueIdentifier,
                    LatestOpportunity = opportunity,
                    LastestUpdate = DateTime.UtcNow
                });
            }
                                                               );

            tradeOpp.LatestOpportunity = opportunity;
            tradeOpp.LastestUpdate     = DateTime.UtcNow;


            // Before writing, we lock the semaphore.
            await tradeOpp.LockingSemaphore.WaitAsync(); // Lock

            try
            {
                // Otherwise the opportunity is still valid.
                // If this is a new opportunity, then we definitely need to save to DB.
                if (isNewOpportunity)
                {
                    using (var ctx = new RBBotContext())
                    {
                        requirements.ForEach(x => { x.TradeOpportunity = tradeOpp; tradeOpp.TradeOpportunityRequirements.Add(x); });
                        tradeOpp.TradeOpportunityValues.Add(newTradeValue);
                        newTradeValue.TradeOpportunity = tradeOpp;

                        ctx.TradeOpportunities.Add(tradeOpp);
                        ctx.TradeOpportunityRequirements.AddRange(requirements);
                        ctx.TradeOpportunityValues.Add(newTradeValue);


                        await ctx.SaveChangesAsync();
                    }
                }
                else
                {
                    // Else we take the requirements and see if anything changed.
                    var requirementsToAdd = new List <TradeOpportunityRequirement>();

                    foreach (var req in requirements)
                    {
                        var toReq = tradeOpp.TradeOpportunityRequirements.Where(x => x.ItemIdentifier == req.ItemIdentifier && x.TradeOpportunityRequirementType == req.TradeOpportunityRequirementType).OrderBy(x => x.Timestamp).LastOrDefault();

                        if (toReq == null || toReq.RequirementMet != req.RequirementMet)
                        {
                            requirementsToAdd.Add(req);
                            req.TradeOpportunityId = tradeOpp.Id;
                        }
                    }

                    newTradeValue.TradeOpportunityId = tradeOpp.Id;

                    using (var ctx = new RBBotContext())
                    {
                        ctx.TradeOpportunityRequirements.AddRange(requirementsToAdd);
                        ctx.TradeOpportunityValues.Add(newTradeValue);
                        await ctx.SaveChangesAsync();
                    }
                }
            }
            finally
            {
                tradeOpp.LockingSemaphore.Release();
            }


            // Return the trade opportunity object.
            return(tradeOpp);
        }