PageRenderTime 9ms CodeModel.GetById 1ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Bitstamp/BitstampClient.Pusher.cs

https://gitlab.com/prog76.trade/Bitstamp
C# | 116 lines | 95 code | 18 blank | 3 comment | 0 complexity | ac12aac26b960619827750b35b2a43be MD5 | raw file
  1using Bitstamp.Models;
  2using Newtonsoft.Json;
  3using Newtonsoft.Json.Linq;
  4using PusherClient;
  5using System;
  6using System.Collections.Concurrent;
  7using System.Collections.Generic;
  8using System.Linq;
  9using System.Reactive.Concurrency;
 10using System.Reactive.Disposables;
 11using System.Reactive.Linq;
 12using System.Reactive.Subjects;
 13using System.Threading;
 14using System.Threading.Tasks;
 15
 16namespace Bitstamp {
 17    public partial class BitstampClient {
 18        private Pusher _pusher;
 19        private ConcurrentDictionary<Type, object> _messages = new ConcurrentDictionary<Type, object>();
 20        private ISubject<object> _observable = new Subject<object>();
 21        private Subscription _orders = new Subscription();
 22        private Subscription _trades = new Subscription();
 23        private Subscription _depth = new Subscription();
 24        private bool _connected = false;
 25        private object _connectionLock = new object();
 26        private object _connectionTarget;
 27
 28        private Task<bool> ConnectAsync(string applicationkey = "de504dc5763aeef9ff52") {
 29            var tcs = new TaskCompletionSource<bool>();
 30            _pusher = new Pusher(applicationkey);
 31
 32            var connected = (ConnectedEventHandler)null;
 33
 34            _orders.Handler = (sender) => {
 35                _orders.Channel.Subscribed -= _orders.Handler;
 36                //_orders.Channel.Bind("order_deleted", (d) => On(OrderDeleted, (d as JObject).AsOrder()));
 37                //_orders.Channel.Bind("order_created", (d) => On(OrderCreated, (d as JObject).AsOrder()));
 38                //_orders.Channel.Bind("order_changed", (d) => On(OrderChanged, (d as JObject).AsOrder()));
 39            };
 40
 41            _trades.Handler = (sender) => {
 42                _trades.Channel.Subscribed -= _trades.Handler;
 43                _trades.Channel.Bind("trade", (d) => OnNext((d as JObject).AsTrade()));
 44            };
 45
 46            _depth.Handler = (sender) => {
 47                _depth.Channel.Subscribed -= _depth.Handler;
 48                _depth.Channel.Bind("data", (d) => OnNext((d as JObject).AsOrderBook()));
 49            };
 50
 51            _pusher.Connected += connected = (sender) => {
 52                _pusher.Connected -= connected;
 53                tcs.SetResult(true);
 54            };
 55
 56            _pusher.ConnectionStateChanged += (s, e) => {
 57            };
 58
 59            _pusher.Connect();
 60
 61            return tcs.Task;
 62        }
 63
 64        private void OnNext<T>(T value) {
 65            _observable.OnNext(value);
 66        }
 67
 68        private IObservable<T> GetObservable<T>(string channel, Subscription subscription) {
 69            LazyInitializer.EnsureInitialized(ref _connectionTarget, ref _connected, ref _connectionLock, () => {
 70                _connected = ConnectAsync().Result;
 71                return null;
 72            });
 73
 74            return (IObservable<T>)_messages.GetOrAdd(typeof(T), type => {
 75                subscription.Channel = _pusher.Subscribe(channel);
 76                subscription.Channel.Subscribed += subscription.Handler;
 77                return _observable.OfType<T>();
 78            });
 79        }
 80
 81        public IObservable<Trade> GetTradesObservable() {
 82            return (IObservable<Trade>)GetObservable<Trade>("live_trades", _trades);
 83        }
 84
 85        public IObservable<OrderBook> GetOrderBookObservable() {
 86            return (IObservable<OrderBook>)GetObservable<OrderBook>("order_book", _depth);
 87        }
 88
 89        public IObservable<Ticker> GetTickerObservable() {
 90            return (IObservable<Ticker>)_messages.GetOrAdd(typeof(Ticker), type => {
 91                return Observable.Create<Ticker>(observer => {
 92                    var ticker = GetTickerAsync().Result;                    
 93                    var observable = Observable.CombineLatest(GetTradesObservable(), GetOrderBookObservable(), (trade, book) => new { Trade = trade, OrderBook = book })
 94                        .Subscribe(a => {
 95                            var ask = a.OrderBook.Asks[0];
 96                            var bid = a.OrderBook.Bids[0];
 97                            var value = new Ticker {
 98                                Ask = ask.Price,
 99                                Bid = bid.Price,
100                                Last = a.Trade.Price,
101                                Volume = ticker.Volume += a.Trade.Amount,
102                                High = Math.Min(ticker.High, a.Trade.Price),
103                                Low = Math.Min(ticker.Low, a.Trade.Price),
104                            };
105                            ticker = value;
106                            observer.OnNext(value);
107                        });
108
109                    observer.OnNext(ticker);
110
111                    return observable;
112                });
113            });
114        }
115    }
116}