/// <summary> /// Place a "Buy" order on the Kraken exchange market. /// </summary> /// <param name="assetName"></param> /// <param name="price"></param> /// <param name="ratio"></param> /// <param name="dt"></param> /// <param name="dry"></param> /// <returns>true if the order is properly placed, false otherwise.</returns> public virtual bool Buy(AssetSymbol assetName, double price, double ratio, DateTime?dt, bool dry) { if ((ratio == 0) || (_privateAPI == false)) { return(false); } var dd = dt ?? DateTime.Now; var fiatSymbol = assetName.QuoteName; // "XRPEUR" => "ZEUR" var assetSymbol = assetName.SymbolName; var totalBalance = Balance(fiatSymbol); // Total balance of the portfolio on this exchange market var amount = (totalBalance * ratio) / 100.0; // Percentage of this total balance that can be used to place order. var bal = Balances(); var availBalance = (double)bal[fiatSymbol]; // Available money for trading. if (amount > availBalance) { amount = availBalance; } var qty = amount / price; if (qty >= assetName.OrderMin) { _logger.Info("Place Order: Buy (" + assetSymbol + ") - Quantity: " + qty + " - Price:" + price + " - Total: " + amount + " " + assetName.QuoteName); var order = RetryHelper <KrakenPlacedOrder> .RetryOnException(_retryTimes, _retryDelay, () => kc.PlaceOrder(assetSymbol, OrderSide.Buy, OrderType.Market, quantity: (decimal)qty, validateOnly: dry)); RateLimiterPenality += 3000; return(order.Success); } return(false); }
/// <summary> /// Return the prices history for a given asset /// </summary> /// <param name="assetName">An normalized asset built from a normalized symbol name.</param> /// <returns></returns> public virtual Dictionary <double, double> PricesHistory(AssetSymbol assetName) { // To Do: Return here the Prices History on the specified symbol var db = new Dictionary <double, double>(); return(db); }
/// <summary> /// The recent trades history for a given symbol /// </summary> /// <param name="assetName"></param> /// <param name="dt"></param> /// <returns></returns> public virtual KrakenTradesResult TradesHistory(AssetSymbol assetName, DateTime dt) { var l = RetryHelper <KrakenTradesResult> .RetryOnException(_retryTimes, _retryDelay, () => kc.GetRecentTrades(assetName.SymbolName, dt)); RateLimiterPenality += 6000; return(l.Data); }
/// <summary> /// Place a 'fake' order on the 'fake' exchange market /// </summary> /// <param name="assetName"></param> /// <param name="orderType"></param> /// <param name="dt"></param> /// <param name="price"></param> /// <param name="amount"></param> /// <returns></returns> protected virtual bool PlaceOrder(AssetSymbol assetName, Trade.TOrderType orderType, DateTime dt, double price, double amount) { var t = new Trade(); t.Timestamp = dt; t.RefPrice = price; t.OrderType = orderType; t.Asset = assetName; var bal = Balances(dt); var balance = bal[assetName.BaseName]; var fees = Fees((price * amount), orderType); decimal total = (decimal)((price * amount) - fees); t.Quantity = (double)amount; if (orderType == Trade.TOrderType.Buy) { balance += (decimal)amount; _assetPortfolio[assetName.QuoteName] -= (double)total; } else { balance -= (decimal)amount; _assetPortfolio[assetName.QuoteName] += (double)total; } _assetPortfolio[assetName.BaseName] = (double)balance; _tradeHistory.Add(t); return(true); }
/// <summary> /// The current price for a given asset /// </summary> /// <param name="assetName"></param> /// <returns></returns> public virtual double MarketPrice(AssetSymbol assetName) { var mk = RetryHelper <Dictionary <string, KrakenRestTick> > .RetryOnException(_retryTimes, _retryDelay, () => kc.GetTickers(symbols: assetName.SymbolName)); RateLimiterPenality += 6000; return((double)mk.Data[assetName.SymbolName].LastTrade.Price); }
/// <summary> /// Place a 'fake' buy order /// </summary> /// <param name="assetName"></param> /// <param name="price"></param> /// <param name="ratio"></param> /// <param name="dt"></param> /// <param name="dry"></param> /// <returns></returns> public override bool Buy(AssetSymbol assetName, double price, double ratio, DateTime?dt, bool dry) { if (ratio == 0) { return(false); } var dd = dt ?? DateTime.Now; var fiatSymbol = assetName.QuoteName; // "XRPEUR" => "ZEUR" var assetSymbol = assetName.SymbolName; var bal = Balances(dd); var availBalance = (double)bal[fiatSymbol]; // Available money for trading. var totalBalance = Balance(fiatSymbol); // Total balance of the portfolio on this exchange market var amount = (totalBalance * ratio) / 100.0; // Percentage of this total balance that can be used to p if (amount > availBalance) { amount = availBalance; } var qty = amount / price; if (qty >= assetName.OrderMin) { NLog.LogManager.GetCurrentClassLogger().Info(dd + "|Place Order: Buy (" + assetSymbol + ") - Quantity: " + qty + " - Price:" + price + " - Total: " + amount + " " + assetName.QuoteName); var success = PlaceOrder(assetName, Trade.TOrderType.Buy, dd, price, qty); RateLimiterPenality += 3000; return(success); } return(false); }
/// <summary> /// Get the prices history for a given asset /// </summary> /// <param name="assetName">The nqme of the asset to get the price history</param> /// <returns>list of prices</returns> public override Dictionary <double, double> PricesHistory(AssetSymbol assetName) { var con = ExportTradesOnDB(assetName); // Get all prices var cmd = new SQLiteCommand(con); cmd.CommandText = @"SELECT timestamp, price FROM history ORDER BY timestamp"; cmd.ExecuteNonQuery(); using SQLiteDataReader rdr = cmd.ExecuteReader(); var _dict = new Dictionary <double, double>(); while (rdr.Read()) { var timestamp = (Int64)rdr["timestamp"]; var dt = new DateTime(timestamp); var oa = (double)dt.ToOADate(); var r = (double)rdr["price"]; if (_dict.ContainsKey(oa)) { _dict[oa] = r; } else { _dict.Add(oa, r); } } _priceHistory.Add(assetName.BaseName, _dict); return(_dict); }
/// <summary> /// Normalize a given symbol name, like "XRPEUR" to the equivalent for Kraken Symbol. /// </summary> /// <param name="symbol">The symbol name (ex: "XRPEUR")</param> /// <returns>A generic Asset name object. </returns> public virtual AssetSymbol NormalizeSymbolName(string symbol) { var sym = RetryHelper <Dictionary <string, KrakenSymbol> > .RetryOnException(_retryTimes, _retryDelay, () => kc.GetSymbols(symbols: symbol)); RateLimiterPenality += 3000; var asset = new AssetSymbol(sym.Data.First().Key, sym.Data.First().Value.BaseAsset, sym.Data.First().Value.QuoteAsset); asset.OrderMin = (double)sym.Data.First().Value.OrderMin; return(asset); }
/// <summary> /// Place a 'fake' sell order /// </summary> /// <param name="assetName"></param> /// <param name="marketPrice"></param> /// <param name="ratio"></param> /// <param name="dt"></param> /// <param name="dry"></param> /// <returns></returns> public override bool Sell(AssetSymbol assetName, double marketPrice, double ratio, DateTime?dt, bool dry) { var dd = dt ?? DateTime.Now; var bal = Balances(dd); var qty = bal[assetName.BaseName]; if (qty > 0) { NLog.LogManager.GetCurrentClassLogger().Info(dd + "|Place Order: Sell (" + assetName.SymbolName + ") - Quantity: " + (double)qty + " - Price:" + marketPrice + " - Total: " + (double)qty * marketPrice + " " + assetName.QuoteName); var success = PlaceOrder(assetName, Trade.TOrderType.Sell, dd, marketPrice, (double)qty); RateLimiterPenality += 3000; return(success); } return(false); }
/// <summary> /// Get the latest trades done for a given asset name /// </summary> /// <param name="assetName">The asset name to retreive the trade history on.</param> /// <returns></returns> public virtual Trade LatestTrade(AssetSymbol assetName) { var mk = RetryHelper <KrakenUserTradesPage> .RetryOnException(_retryTimes, _retryDelay, () => kc.GetTradeHistory()); RateLimiterPenality += 6000; var rt = mk.Data.Trades.FirstOrDefault(x => x.Value.Symbol == assetName.SymbolName); if (rt.Value == null) { return(null); } var trade = new Trade(); trade.RefPrice = (double)rt.Value.Price; trade.OrderType = rt.Value.Side == Kraken.Net.Objects.OrderSide.Buy?Trade.TOrderType.Buy:Trade.TOrderType.Sell; return(trade); }
/// <summary> /// Place a "Sell" order on the Kraken exchange market. /// </summary> /// <param name="assetName">The crypto asset to sell for a given currency. ex: "BTCEUR" ></param> /// <param name="price">The wanted price (on the currency).</param> /// <param name="ratio">the pourcentage to qpply on the transaction.</param> /// <param name="dt">When schedule that order.</param> /// <param name="dry">Is it for real or not?</param> /// <returns>true if the order was properly placed, false otherwise.</returns> public virtual bool Sell(AssetSymbol assetName, double price, double ratio, DateTime?dt, bool dry) { if (_privateAPI == false) { return(false); } var dd = dt ?? DateTime.Now; var bal = Balances(); var qty = bal[assetName.BaseName]; if (qty > 0) { _logger.Info("Place Order: Sell (" + assetName.SymbolName + ") - Quantity: " + qty + " - Price:" + price + " - Total: " + (double)qty * price + " " + assetName.QuoteName); var order = RetryHelper <KrakenPlacedOrder> .RetryOnException(_retryTimes, _retryDelay, () => kc.PlaceOrder(assetName.SymbolName, OrderSide.Sell, OrderType.Market, quantity: (decimal)qty, validateOnly: dry)); RateLimiterPenality += 3000; return(order.Success); } return(false); }
/// <summary> /// Get the latest transaction performed for a given asset /// </summary> /// <param name="assetName"></param> /// <returns></returns> public override Trade LatestTrade(AssetSymbol assetName) { if (_tradeHistory.Count == 0) { var tr = new Trade(); tr.Asset = assetName; return(tr); } var hist = from h in _tradeHistory where h.Asset.SymbolName == assetName.SymbolName orderby h.Timestamp descending select h; RateLimiterPenality += 6000; if (hist.Count() == 0) { var tr = new Trade(); tr.Asset = assetName; return(tr); } return(hist.First()); }
/// <summary> /// Get the price history for a given asset and store it into a sqlite DB. /// </summary> /// <param name="assetName"></param> /// <returns></returns> public SQLiteConnection ExportTradesOnDB(AssetSymbol assetName) { string cs = @"URI=file:" + assetName.SymbolName + ".db"; var con = new SQLiteConnection(cs); con.Open(); var cmd = new SQLiteCommand(con); cmd.CommandText = @"CREATE TABLE IF NOT EXISTS history (my_id integer PRIMARY KEY, timestamp integer, price double, amount double, unique (timestamp,price,amount))"; cmd.ExecuteNonQuery(); cmd.CommandText = @"CREATE TABLE IF NOT EXISTS lastcheck (timestamp integer)"; cmd.ExecuteNonQuery(); cmd.CommandText = @"SELECT COUNT(*) FROM history"; var count = Convert.ToInt32(cmd.ExecuteScalar()); var dt = new DateTime(2008, 1, 1, 0, 0, 0); if (count != 0) { cmd.CommandText = @"SELECT * FROM lastcheck"; using (SQLiteDataReader rdr = cmd.ExecuteReader()) { if (rdr.HasRows) { if (rdr.Read()) { var timestamp = rdr.GetInt64(0); dt = new DateTime(timestamp); } } } } else { cmd.CommandText = @"INSERT INTO lastcheck (timestamp) VALUES (@timestamp)"; cmd.Parameters.AddWithValue("@timestamp", dt.Ticks); cmd.Prepare(); cmd.ExecuteNonQuery(); } bool fullyUpdated = false; while (!fullyUpdated) { var trades = TradesHistory(assetName, dt); using (var transaction = con.BeginTransaction()) { foreach (var it in trades.Data) { cmd.CommandText = @"INSERT OR IGNORE INTO history(timestamp, price, amount) VALUES (@timestamp, @price, @amount)"; cmd.Parameters.AddWithValue("@timestamp", it.Timestamp.Ticks); cmd.Parameters.AddWithValue("@price", it.Price); cmd.Parameters.AddWithValue("@amount", it.Quantity); cmd.Prepare(); cmd.ExecuteNonQuery(); } transaction.Commit(); } dt = trades.Last; cmd.CommandText = @"UPDATE lastcheck SET timestamp = '" + dt.Ticks + "'"; cmd.ExecuteNonQuery(); if (trades.Data.Count() < 1000) { fullyUpdated = true; } base.PreventRateLimit(); // To avoid a rate limit exception on Kraken API public calls. } return(con); }