Ejemplo n.º 1
0
        public string GetDescription()
        {
            var description = $"{FundName}({FundCode}) 以 {AvgCost.ToString("F4")} 的价格持有 {Share.ToString("F2")} 份," +
                              $"根据 {NavDate.ToString("yyyy-MM-dd")} 的净值({FundNav.ToString("F4")}) 计算," +
                              $"市值达 {MarketValue.ToString("F2")},盈利 {PositionProfit.ToString("F2")}," +
                              $"实现 {PositionProfitRate.ToString("P")} 收益率";

            if (Abilities?.Any() ?? false)
            {
                Abilities.ForEach(a => description += $"\n{a.GetDescription()}");
            }
            return(description);
        }
Ejemplo n.º 2
0
        public async Task <bool> SaveOrUpdateAsync(AvgCost avgCost)
        {
            var updOpts = new UpdateOptions {
                IsUpsert = true
            };
            var updDef = new UpdateDefinitionBuilder <AvgCost>()
                         .SetOnInsert(x => x.Customer, avgCost.Customer)
                         .SetOnInsert(x => x.Symbol, avgCost.Symbol)
                         .Set(x => x.Price, avgCost.Price)
                         .Set(x => x.Quantity, avgCost.Quantity)
                         .PushEach(x => x.History, avgCost.History);

            var result = await _collection.UpdateOneAsync(x => x.Customer == avgCost.Customer && x.Symbol == avgCost.Symbol, updDef, updOpts);

            return(result.IsAcknowledged);
        }
Ejemplo n.º 3
0
        static async Task Main(string[] args)
        {
            var          container           = DependencyInjectionConfig.InitializeContainer();
            var          repository          = container.GetInstance <IAvgCostRepository>();
            const string TradesQueueName     = "trades_queue";
            const string RealTimePubExchange = "realtime_pub_exchange";
            var          factory             = new ConnectionFactory()
            {
                HostName = "localhost", UserName = "******", Password = "******"
            };
            var concurrentDictionary = new ConcurrentDictionary <string, AvgCost>();

            using var connection = factory.CreateConnection();
            using var channel    = connection.CreateModel();
            var tradesTransformBlock = new TransformBlock <Trade, AvgCost>(trade =>
            {
                if (concurrentDictionary.TryGetValue(trade.Key(), out var avgCost))
                {
                    //Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {avgCost} {avgCost.Quantity}");
                    avgCost.Quantity += trade.Quantity;
                    if (avgCost.Quantity == 0)
                    {
                        avgCost.Price = 0;
                    }
                    else if (trade.Quantity > 0 && avgCost.Quantity > 0)
                    {
                        avgCost.Price = Math.Round(((avgCost.Price * avgCost.Quantity + trade.Price * trade.Quantity) / avgCost.Quantity), 6);
                    }
                    avgCost.History = new[] { trade };

                    concurrentDictionary.TryRemove(avgCost.Key(), out var avgCostOld);
                    concurrentDictionary.TryAdd(avgCost.Key(), avgCost);
                    return(avgCost);
                }
                avgCost = new AvgCost
                {
                    Customer = trade.Client,
                    Quantity = trade.Quantity,
                    Symbol   = trade.Symbol,
                    Price    = trade.Price,
                    History  = new[] { trade }
                };
                concurrentDictionary.TryAdd(avgCost.Key(), avgCost);
                return(avgCost);
            }, new ExecutionDataflowBlockOptions {
                BoundedCapacity = 10000, EnsureOrdered = true
            });

            var linkOptions = new DataflowLinkOptions {
                PropagateCompletion = true
            };
            var broadcastBlock = new BroadcastBlock <AvgCost>(msg => msg);
            var pubActionBlock = new ActionBlock <AvgCost>(avgCost =>
            {
                var basicProps        = channel.CreateBasicProperties();
                basicProps.Expiration = "10000";
                channel.BasicPublish(RealTimePubExchange, $"{avgCost.Customer}", body: Encoding.UTF8.GetBytes(avgCost.ToString()), basicProperties: basicProps);
            }, new ExecutionDataflowBlockOptions {
                EnsureOrdered = true
            });
            var batchBlock = new BatchBlock <AvgCost>(1000);
            var persistMongoActionBlock = new ActionBlock <IEnumerable <AvgCost> >(async avgCosts => await repository.SaveOrUpdateManyAsync(avgCosts));

            tradesTransformBlock.LinkTo(broadcastBlock, linkOptions);
            broadcastBlock.LinkTo(pubActionBlock, linkOptions);
            broadcastBlock.LinkTo(batchBlock, linkOptions);
            batchBlock.LinkTo(persistMongoActionBlock, linkOptions);

            channel.ExchangeDeclare(RealTimePubExchange, ExchangeType.Topic);
            channel.QueueDeclare(TradesQueueName, true, false, false);
            channel.BasicQos(0, 1, false);

            var consumer = new EventingBasicConsumer(channel);

            consumer.Received += async(model, ea) =>
            {
                var body  = ea.Body;
                var trade = JsonSerializer.Deserialize <Trade>(Encoding.UTF8.GetString(body));

                tradesTransformBlock.Post(trade);
                channel.BasicAck(ea.DeliveryTag, false);
                Console.WriteLine("Processed {0}", trade);
            };

            channel.BasicConsume(TradesQueueName, false, consumer);

            await Task.WhenAll(tradesTransformBlock.Completion, batchBlock.Completion, pubActionBlock.Completion);

            tradesTransformBlock.Complete();
            Console.ReadLine();
        }