/// <summary> /// Retrieves candles. We first look in a local transactions file, then we get the missing candles from bitcoincharts or bitcoinwisdom /// </summary> /// <param name="pair"></param> /// <param name="fromDateTime"></param> /// <param name="candleDurationsInMinutes"></param> /// <param name="toDateTime"></param> /// <returns></returns> public static IList<OHLC> LoadCandles(CurrencyPair pair, DateTime fromDateTime, int candleDurationsInMinutes, DateTime? toDateTime = null) { //Try to get candles from local transactions var candles = _csvRepository.GetCandlesFromCSVTransactions(fromDateTime, toDateTime, candleDurationsInMinutes, pair); var lastCandle = candles.LastOrDefault(); if (toDateTime == null) { toDateTime = DateTime.UtcNow; } if (lastCandle != null) { candles.Remove(lastCandle); } var newLast = candles.LastOrDefault(); DateTime minTime = newLast != null ? newLast.Date.AddSeconds(1) : fromDateTime; //Then we try to get more candles from websites providing historic data if (minTime.AddHours(1) < toDateTime)//If older than 1 H, we need to get data from bitcoincharts/bitcoinwisdom { if (pair.Item1 == CurrencyCodes.BTC && !string.IsNullOrEmpty(pair.Exchange.BitcoinChartsCode)) { var newestCandles = GetCandlesFromBitcoincharts(minTime, candleDurationsInMinutes, pair.Exchange.BitcoinChartsCode, pair.Item2); candles = candles.Union(newestCandles).ToList(); if (candles.Count == 0) { newestCandles = GetCandlesFromBitcoinWisdom(pair, fromDateTime, candleDurationsInMinutes); candles = candles.Union(newestCandles).ToList(); } } else { var newestCandles = GetCandlesFromBitcoinWisdom(pair, fromDateTime, candleDurationsInMinutes); candles = candles.Union(newestCandles).ToList(); } } var recentCandles = GetRecentCandlesFromTransactions(fromDateTime, candleDurationsInMinutes, pair); foreach (OHLC newCandle in recentCandles) { var existingCandle = candles.FirstOrDefault(e => e.Date == newCandle.Date); if (existingCandle != null) { existingCandle.High = newCandle.High > existingCandle.High ? newCandle.High : existingCandle.High; existingCandle.Low = newCandle.Low < existingCandle.Low ? newCandle.Low : existingCandle.Low; existingCandle.Close = newCandle.Close; } else { candles.Add(newCandle); } } return candles; }
/// <summary> /// Initialises a new instance of the class /// </summary> public TickerControl() { InitializeComponent(); EventAggregator.Instance.Subscribe<PairSelected>(m => { if (m.SelectorType == SelectorType.Main) { _selectedPair = m.Pair; if (_tickerToken != null) { _tickerToken.Cancel(); _lastPrice = 0; } } }); this.Load += (s, e) => { if (!this.DesignMode && !(ParentForm as MainForm).IsDesignMode) { tmrTicker.Start(); } }; }
/// <summary> /// Clear fields and gets the fee for the selected pair /// </summary> private void OnPairChanged(PairSelected m) { if (m.SelectorType != SelectorType.Main) { return; } try { _selectedPair = m.Pair; lblItem1Balance.Text = lblItem2Balance.Text = string.Empty; txtBuyAmount.Text = txtBuyPrice.Text = txtSellAmount.Text = txtSellPrice.Text = string.Empty; var feeRes = _proxy.GetFee(m.Pair); lblCurrency1.Text = lblCurrency2.Text = m.Pair.Item2; lblSellAmountCurrency.Text = lblBuyAmountCurrency.Text = m.Pair.Item1; _fee = feeRes.Success ? feeRes.Result : new Fee { BuyFee = 0.5m, SellFee = 0.5m }; lblBuyFee.Text = lblSellFee.Text = "0"; lblBuyTotal.Text = lblSellTotal.Text = "0"; UpdateBalance(false); } catch (Exception ex) { Logger.Log(ex); ErrorHelper.DisplayErrorMessage(ex.ToString()); } }
public CallResult<Balance> GetBalance(CurrencyPair pair) { var bal = new Balance { }; bal.Balances[pair.Item1] = _availableItem1; bal.Balances[pair.Item2] = _availableItem2; return new CallResult<Balance>(bal); }
/// <summary> /// Called when the main screen's pair changes /// </summary> /// <param name="message"></param> private void OnPairSelected(PairSelected message) { if (message.SelectorType == SelectorType.Main) { _selectedPair = message.Pair; dgvOpenOrders.Rows.Clear(); colAmount.HeaderText = message.Pair.Item1 + " Amount"; colPrice.HeaderText = "Price in " + message.Pair.Item2; colTotalPrice.HeaderText = "Total Price in " + message.Pair.Item2; RefreshOrders(false);//Auto refresh of open orders } }
public CallResult<OrderDetails> PlaceSellOrder(decimal amount, decimal price, CurrencyPair pair) { System.Diagnostics.Debug.WriteLine(string.Format("Selling {0:0.00} {2} @ {1:0.00} {3}", amount, price, pair.Item1, pair.Item2)); _availableItem2 += (amount * price - amount * price * _fee.SellFee / 100); _availableItem1 -= amount; return new CallResult<OrderDetails>(new OrderDetails { Amount = amount, Price = price, Type = OrderType.Sell }); }
/// <summary> /// Initialises a new instance of the class /// </summary> /// <param name="settings">the strategy settings</param> /// <param name="tradingIndicator">The indicator to use</param> public BaseTradingStrategy(StrategySettings settings, ITradingIndicator tradingIndicator) { _settings = settings; _tradingIndicator = tradingIndicator; _pair = settings.Pair; Actions = new List<MarketAction>(); // Only do back testing trading for now _proxy = new FakeExchange(); if (_proxy is FakeExchange) { (_proxy as FakeExchange).Init(settings.InitialItem1Balance, settings.InitialItem2Balance, settings.BuyFee, settings.SellFee); } }
/// <summary> /// Initialises a new instance of the class /// </summary> public OrderBookControl() { InitializeComponent(); EventAggregator.Instance.Subscribe<ApplicationStartMessage>(m => { UpdateOrderBook(); tmrRefresh.Start(); }); btnRefresh.Click += (s, e) => UpdateOrderBook(); tmrRefresh.Tick += (s, e) => UpdateOrderBook(); EventAggregator.Instance.Subscribe<PairSelected>(m => { if (m.SelectorType == SelectorType.Main) { _selectedPair = m.Pair; } }); }
/// <summary> /// Initialises a new instance of the class /// </summary> public MainForm() { InitializeComponent(); this.Text = CoinTNet.Common.Constants.ApplicationConstants.ApplicationName; EventAggregator.Instance.Subscribe<StatusUpdateMessage>(m => UpdateStatus(m.Message)); // this.Shown += (s, e) => OnBtnRefreshClick(); dataSelector.RefreshClicked += (s, e) => OnBtnRefreshClick(); dataSelector.OnPairChanged += (s, e) => OnPairChanged(); dataSelector.UseLiveData = true; _selectedPair = dataSelector.SelectedPair; _indicatorsForm = new IndicatorsForm(); _indicatorsForm.IndicatorOptionsChanged += (s, options) => { myChartControl.NotifyIndicatorsChanged(options); }; myChartControl.NotifyIndicatorsChanged(_indicatorsForm.IndicatorOptions); this.Load += (s, e) => EventAggregator.Instance.Publish(new ApplicationStartMessage()); this.Text = string.Format("{0} - {1}a", ApplicationConstants.ApplicationName, ApplicationConstants.CurrentVersion); }
/// <summary> /// Initialises a new instance of the class /// </summary> public TickerControl() { InitializeComponent(); EventAggregator.Instance.Subscribe<PairSelected>(m => { if (m.SelectorType == SelectorType.Main) { _selectedPair = m.Pair; if (_tickerToken != null) { _tickerToken.Cancel(); _lastPrice = 0; } _24High = _24Low = null; //If Cryptsy, we cache the last 24 hour high/low if (m.Pair.Exchange.InternalCode == ExchangesInternalCodes.Cryptsy) { var mRes = (ExchangeProxyFactory.GetProxy(_selectedPair.Exchange.InternalCode) as DAL.Exchanges.CryptsyWrapper).CryptsyProxy.GetActiveMarkets(); if (mRes.Success) { var market = mRes.Result.Find(ma => ma.ID == _selectedPair.ID); _24Low = market.Low; _24High = market.High; } } } }); this.Load += (s, e) => { if (!this.DesignMode && !(ParentForm as MainForm).IsDesignMode) { tmrTicker.Start(); } }; }
/// <summary> /// Retrieve candles from a file containing transactions /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="candleDurationInMinutes"></param> /// <param name="pair"></param> /// <param name="inputFile"></param> /// <returns></returns> public List<OHLC> GetCandlesFromCSVTransactions(DateTime from, DateTime? to, int candleDurationInMinutes, CurrencyPair pair, string inputFile = null) { if (string.IsNullOrEmpty(inputFile)) { inputFile = GetTransactionsStoreFileName(pair); } if (!File.Exists(inputFile)) { return new List<OHLC>(); } var fromTimeStamp = BitstampAPI.UnixTimeHelper.GetFromDateTime(from); var toTimeStamp = to != null ? BitstampAPI.UnixTimeHelper.GetFromDateTime(to.Value) : (uint?)null; long? nextStamp = null; int candleDurationInSeconds = candleDurationInMinutes * 60; List<decimal> pricesForCurrentCandle = new List<decimal>(); List<OHLC> candles = new List<OHLC>(); using (var sr = new StreamReader(inputFile)) { while (!sr.EndOfStream) { var line = sr.ReadLine(); var buf = line.Split(new[] { ',' }); long transTimeStamp = Convert.ToInt64(buf[0]); if (transTimeStamp < fromTimeStamp) { continue; } decimal price = Convert.ToDecimal(buf[1], CultureInfo.InvariantCulture); if (nextStamp == null) { nextStamp = transTimeStamp + candleDurationInSeconds; } if (transTimeStamp < nextStamp) { pricesForCurrentCandle.Add(price); } else//New candle { OHLC ohlc = new OHLC(); if (pricesForCurrentCandle.Count > 0) { ohlc = new OHLC { Open = pricesForCurrentCandle.First(), High = pricesForCurrentCandle.Max(), Low = pricesForCurrentCandle.Min(), Close = pricesForCurrentCandle.Last(), Date = BitstampAPI.UnixTimeHelper.ConvertToDateTime((uint)nextStamp) }; } else//No prices for this candle... use previous candle's close value { var prev = candles.Last(); ohlc = new OHLC { Open = prev.Close, High = prev.Close, Low = prev.Close, Close = prev.Close, Date = BitstampAPI.UnixTimeHelper.ConvertToDateTime((uint)nextStamp) }; } candles.Add(ohlc); nextStamp = nextStamp + candleDurationInSeconds; pricesForCurrentCandle.Clear(); if (toTimeStamp != null && nextStamp > toTimeStamp.Value) { break; } } } }//using return candles; }
/// <summary> /// Gets the path of the file where transactions for a given currency pair are stored /// </summary> /// <param name="pair"></param> /// <returns></returns> private string GetTransactionsStoreFileName(CurrencyPair pair) { return Path.Combine(Environment.CurrentDirectory, string.Format("{0}{1}{2}.csv", pair.Exchange.BitcoinChartsCode, pair.Item1, pair.Item2)); }
public CallResult<OrderBook> GetOrderBook(CurrencyPair pair) { throw new NotImplementedException(); }
public CallResult<Fee> GetFee(CurrencyPair pair) { return new CallResult<Fee>(_fee); }
/// <summary> /// Retrieves candles from BitcoinWisdom /// </summary> /// <param name="pair"></param> /// <param name="from"></param> /// <param name="candlesDurationInMin"></param> /// <returns></returns> private static IList<OHLC> GetCandlesFromBitcoinWisdom(CurrencyPair pair, DateTime from, int candlesDurationInMin) { try { var p = GetBitcoinWisdomProxy(); var trades = p.GetCandles(from, candlesDurationInMin, pair.Exchange.BitcoinWisdomCode, pair.Item1, pair.Item2); return trades.Select(t => new OHLC { Close = t.Close, Open = t.Open, High = t.High, Date = t.DateTime.DateTime, Low = t.Low, TimeStamp = t.TimeStamp, }).ToList(); } catch (Exception ex) { Logger.Log(ex); MessageBox.Show(ex.ToString()); } return new List<OHLC>(); }
public CallResult<OpenOrders> GetOpenOrders(CurrencyPair pair) { return new CallResult<OpenOrders>(new OpenOrders()); }
/// <summary> /// Gets the unit for the fee for a given pair /// </summary> /// <param name="pair">The currency pair</param> /// <param name="type">The type of order (buy/sell)</param> /// <returns></returns> public string GetFeeUnit(CurrencyPair pair, OrderType type) { return type == OrderType.Buy ? pair.Item1 : pair.Item2; }
public CallResult<TransactionList> GetTransactions(bool lastMin, CurrencyPair pair) { throw new NotImplementedException(); }
/// <summary> /// Calculates candles from a file containing transactions /// </summary> /// <param name="pair"></param> /// <param name="candlesDurationInMin"></param> /// <param name="fromDateTime"></param> /// <param name="toDateTime"></param> /// <returns></returns> public static IList<OHLC> ReadCandlesFromCSVTransactions(CurrencyPair pair, int candlesDurationInMin, DateTime fromDateTime, DateTime? toDateTime = null) { var rep = new CSVCandleRepository(); string market = pair != null ? pair.Exchange.BitcoinChartsCode : string.Empty; string currency = pair != null ? pair.Item2 : string.Empty; return rep.GetCandlesFromCSVTransactions(fromDateTime, toDateTime, candlesDurationInMin, pair); }
private void OnPairChanged() { _candles.Clear(); myChartControl.Clear(); _selectedPair = dataSelector.SelectedPair; OnBtnRefreshClick(); }
/// <summary> /// Updates a list of candles with the most recent data from a given exchange (Called when ticker refreshes) /// </summary> /// <param name="from">The from date</param> /// <param name="candlesDurationInMin">The period' duration in minutes</param> /// <param name="existingCandles">A list of existing candles</param> /// <returns>True if the update was successful</returns> public static bool UpdateCandlesWithLiveData(DateTime from, int candlesDurationInMin, IList<OHLC> existingCandles, CurrencyPair pair) { try { var proxy = ExchangeProxyFactory.GetProxy(pair.Exchange.InternalCode); //We first get the transactions for the last minute var transactionsRes = proxy.GetTransactions(true, pair);// if (!transactionsRes.Success) { return false; } var transactions = transactionsRes.Result.Transactions; transactions.Reverse();//Make sure they are in ASC order transactions = transactions.Where(t => t.Date >= from).ToList(); // Create trade list (required to calculate OHLC) IList<BitcoinCharts.Models.Trade> list = (from trade in transactions select new BitcoinCharts.Models.Trade() { Datetime = trade.Date, Price = trade.Price, Quantity = trade.Amount, Symbol = pair.Item2 }).ToList(); //Check if we need to create another candle var lastCandle = existingCandles.LastOrDefault(); if (list.Count == 0 && lastCandle != null) { if (lastCandle.Date.Subtract(DateTime.MinValue).TotalMinutes / candlesDurationInMin != DateTime.Now.Subtract(DateTime.MinValue).TotalMinutes / candlesDurationInMin) { list.Add(new BitcoinCharts.Models.Trade { Datetime = lastCandle.Date.AddMilliseconds(candlesDurationInMin), Price = lastCandle.Close, Quantity = 0, Symbol = pair.Item2 }); } } // Calculate trades IList<OHLC> recentCandles = CandlesProvider.CalculateOHLCFromTrades(list, candlesDurationInMin, TradeSource.Bitstamp); foreach (OHLC newCandle in recentCandles) { var existingCandle = existingCandles.FirstOrDefault(e => e.Date == newCandle.Date); if (existingCandle != null) { existingCandle.High = newCandle.High > existingCandle.High ? newCandle.High : existingCandle.High; existingCandle.Low = newCandle.Low < existingCandle.Low ? newCandle.Low : existingCandle.Low; existingCandle.Close = newCandle.Close; existingCandle.TradeSource = TradeSource.Bitstamp; //recentCandles = recentCandles.Skip(1).ToList(); } else { existingCandles.Add(newCandle); } } return recentCandles.Count() > 0; } catch (Exception ex) { Logger.Log(ex); MessageBox.Show(ex.ToString()); } return false; }
public CallResult<Ticker> GetTicker(CurrencyPair pair) { throw new NotImplementedException(); }
/// <summary> /// Retrieves recent transactions from the exchange to calculate recent candles /// </summary> /// <param name="candlesDurationInMin"></param> /// <returns></returns> private static IList<OHLC> GetRecentCandlesFromTransactions(DateTime from, int candlesDurationInMin, CurrencyPair pair) { try { var proxy = ExchangeProxyFactory.GetProxy(pair.Exchange.InternalCode); var tradesRes = proxy.GetTransactions(false, pair); if (!tradesRes.Success) { return new List<OHLC>(); } var trades = tradesRes.Result.Transactions; trades.Reverse(); // Create trade list (required to calculate OHLC) IList<BitcoinCharts.Models.Trade> list = (from trade in trades select new BitcoinCharts.Models.Trade() { Datetime = trade.Date, Price = trade.Price, Quantity = trade.Amount, Symbol = pair.Item2 }).ToList(); // Calculate trades IList<OHLC> candles = CandlesProvider.CalculateOHLCFromTrades(list, candlesDurationInMin, TradeSource.Bitstamp).Where(c => c.Date >= from).ToList(); return candles; } catch (Exception ex) { Logger.Log(ex); MessageBox.Show(ex.ToString()); } return new List<OHLC>(); }
public void AssignPairs(CurrencyPair[] pairs) { CurrencyPairs = pairs; CurrencyPairs.ToList().ForEach(cp => cp.Exchange = this); }
/// <summary> /// Updates the labels depending on the selected currency pair /// </summary> /// <param name="pair"></param> private void UpdateLabels(CurrencyPair pair) { lblMinAmountItem1ToKeep.Text = string.Format("Min amount {0} to keep", pair.Item1); lblMinAmountItem2ToKeep.Text = string.Format("Min amount {0} to keep", pair.Item2); lblMaxAmountItem1PerSell.Text = string.Format("Max Nb {0}/ sell order", pair.Item1); lblMaxAmountItem2PerBuy.Text = string.Format("Max Nb {0}/ buy order", pair.Item2); lblInitialItem1Balance.Text = string.Format("Initial {0} balance (Back test)", pair.Item1); lblInitialItem2Balance.Text = string.Format("Initial {0} balance (Back test)", pair.Item2); }
/// <summary> /// Called when slow timer ticks, to update displayed candles with latest data /// </summary> /// <param name="fetchLiveData"></param> /// <param name="candlesDurationInMin"></param> private void UpdateCandles(DateTime fromDate, int candlesDurationInMin, CurrencyPair pair) { lock (this) { // First load history if (_candles.Count > 0) { UpdateStatus("Fetching new data"); CandlesProvider.UpdateCandlesWithLiveData(fromDate, candlesDurationInMin, _candles, pair); } try { UpdateStatus("Ready..."); } catch (Exception ex) { UpdateStatus(string.Format("Error during Update: {0}", ex.Message)); } } }