protected CStrategy(Dictionary <int, Tuple <OrderSide, CProduct> > dctLegs) { this.server = CStrategyServer.Server; this.dctLegs = dctLegs; processStrategy = false; CurrentLeg = 1; DctStrategyProducts = new ConcurrentDictionary <String, CProduct>(); DctStrategyOrders = new ConcurrentDictionary <String, COrder>(); DctLegToOrder = new ConcurrentDictionary <int, COrder>(); // link everything up for (int i = 1; i <= dctLegs.Count; i++) { // assign Strategy to Leg dctLegs[i].Item2.colStrategy.Add(this); // assign Product to Strategy Product Collection CProduct product = dctLegs[i].Item2; if (!DctStrategyProducts.ContainsKey(product.Symbol)) { DctStrategyProducts[product.Symbol] = product; } // assign Product to Exchange Product Collection if (!dctLegs[i].Item2.Exchange.dctExchangeProducts.ContainsKey(product.Symbol)) { dctLegs[i].Item2.Exchange.dctExchangeProducts.Add(product.Symbol, product); } //TODO: any more linking } }
public override void trade(CStrategy strategy, int?leg, OrderSide?side, CProduct product, Double size, Double price) { try { server.AddLog("Init " + side + " " + product.Symbol + " Trade on " + api.Name); ExchangeTicker ticker = api.GetTicker(product.Symbol); ExchangeOrderResult result = api.PlaceOrder(new ExchangeOrderRequest { Amount = (Decimal)size, IsBuy = (side == OrderSide.Buy), Price = (Decimal)price, Symbol = product.Symbol }); System.Threading.Thread.Sleep(100); String orderID = result.OrderId; server.AddLog("Calling Order OrderID: " + result.OrderId + " Date: " + result.OrderDate + " Result: " + result.Result); COrder order = new COrder(orderID); order.Product = product; order.Side = side.GetValueOrDefault(); order.Size = size; order.Price = price; String orderStatus = result.Result.ToString(); if (orderStatus.Equals("OK") || orderStatus.Equals("Sent")) { order.Status = COrder.OrderState.Sent; } else { order.Status = COrder.OrderState.Unknown; } order.Strategy = strategy; order.Exchange = this; order.TimeStampSent = result.OrderDate; server.AddLog("Created Order " + this.Name + " " + orderID + " " + product + " " + side + " " + size + " " + price); // add order to global Orders server.colServerOrders.Add(order); server.dctIdToOrder[orderID] = order; // add order to strategy orders strategy.DctStrategyOrders[orderID] = order; if (leg != null) { strategy.DctLegToOrder[(int)leg] = order; } // cleanup order.updateGUI(); } catch (Exception ex) { server.AddLog(ex.Message); } }
public void tradeNext(ServerType serverType, Double dUSD, Boolean active) { OrderSide side = dctLegs[CurrentLeg].Item1; CProduct product = dctLegs[CurrentLeg].Item2; Double size = 0.00001; Double price; if (product.Symbol.EndsWith("USD") || product.Symbol.EndsWith("USDT")) { size = dUSD / (double)product.Last; } else if (product.Symbol.StartsWith("USD") || product.Symbol.StartsWith("USDT")) { if (side == OrderSide.Buy) { size = dUSD; } else { size = dUSD / (double)product.Last; } } else { String productUSD = product.Symbol.Substring(0, 3); if (product.Exchange is CKuCoin) { productUSD += "-"; } productUSD += "USDT"; CProduct productExchange = DctStrategyProducts[productUSD]; if (productExchange.Symbol.Equals(productUSD)) { size = dUSD / (double)productExchange.Last; } } if (active) { price = ((Double)product.Bid + (Double)product.Ask) / 2.0; } else if (side == OrderSide.Buy) { price = (Double)product.Bid; } else { price = (Double)product.Ask; } dctLegs[CurrentLeg].Item2.Exchange.trade(this, CurrentLeg, side, product, Math.Round(size, product.PrecisionSize), Math.Round(price, product.PrecisionPrice)); if (++CurrentLeg > dctLegs.Count) { CurrentLeg = 1; } }
internal Double GetSize(OrderSide side, CProduct product) { // create new order double dUSD = server.TradeUSD.GetValueOrDefault(); Double size = 0.00001; if (product.Symbol.EndsWith("USD") || product.Symbol.EndsWith("USDT")) { size = dUSD / (double)product.Last; } else if (product.Symbol.StartsWith("USD") || product.Symbol.StartsWith("USDT")) { if (side == OrderSide.Buy) { size = dUSD; } else { size = dUSD / (double)product.Last; } } else { String productUSD = product.Symbol.Substring(0, 3); if (product.Exchange is CKuCoin) { productUSD += "-"; } productUSD += "USDT"; CProduct productExchange = DctStrategyProducts[productUSD]; if (productExchange.Symbol.Equals(productUSD)) { size = dUSD / (double)productExchange.Last; if (product.MinSize.HasValue) { size = Math.Max(size, product.MinSize.GetValueOrDefault()); } } } return(size); }
public override async void cancel(string orderID) { try { String endpoint = "/v1/cancel-order"; // API endpoint COrder order = server.dctIdToOrder[orderID]; CProduct product = order.Product; Dictionary <string, string> parameters = new Dictionary <string, string> { { "orderOid", orderID }, { "symbol", product.Symbol }, { "type", order.Side.ToString().ToUpper() } }; HttpRequestMessage requestMessage = KuCoinPrivate(endpoint, parameters, HttpMethod.Post); HttpClient httpClient = new HttpClient(); // Send the request to the server HttpResponseMessage response = await httpClient.SendAsync(requestMessage); // get back cancel message string json = await response.Content.ReadAsStringAsync(); // parse order String dynamic cancelorderData = JsonConvert.DeserializeObject(json); var orders = cancelorderData.data; var success = cancelorderData.success; Boolean bSuccess; Boolean.TryParse(success.ToString(), out bSuccess); if (bSuccess) { order.Status = COrder.OrderState.Cancelled; } order.TimeStampLastUpdate = DateTime.Now; order.updateGUI(); server.AddLog(json); } catch (Exception ex) { server.AddLog(ex.Message); } }
public override async void pollPositions(object source, ElapsedEventArgs e) { if (pollingPositions) { return; } else { pollingPositions = true; } try { Dictionary <String, Decimal> positions = await api.GetAmountsAsync(); foreach (var pos in positions) { var coinType = pos.Key; var balance = pos.Value; String symbol = exchangeUSD(coinType.ToString()); if (dctExchangeProducts.ContainsKey(symbol)) { CProduct product = dctExchangeProducts[symbol]; product.TimeStampLastBalance = DateTime.Now; Double dbal = 0; Double.TryParse(balance.ToString(), out dbal); product.SetBalance(dbal); product.updateGUI(); } } } catch (Exception ex) { server.AddLog(ex.Message); } pollingPositions = false; }
public override void cycleStrategy() { if (processStrategy) { return; } else { processStrategy = true; } try { Double profitUSD = server.TradeUSD.GetValueOrDefault() * server.MinProfit.GetValueOrDefault(); switch (State) { case StrategyState.Inactive: break; case StrategyState.Active: case StrategyState.Continuous: if (Profit >= profitUSD) { State = StrategyState.MakerSend; DctLegToOrder.Clear(); goto case StrategyState.MakerSend; } break; case StrategyState.MakerSend: CurrentLeg = MakerLeg; double dUSD = server.TradeUSD.GetValueOrDefault(); OrderSide sideMaker = dctLegs[CurrentLeg].Item1; CProduct productMaker = dctLegs[CurrentLeg].Item2; Double sizeMaker = GetSize(sideMaker, productMaker); Double priceMaker = (double)(sideMaker == OrderSide.Buy ? productMaker.Bid : productMaker.Ask); dctLegs[MakerLeg].Item2.Exchange.trade(this, MakerLeg, sideMaker, productMaker, Math.Round(sizeMaker, productMaker.PrecisionSize), Math.Round(priceMaker, productMaker.PrecisionPrice)); State = StrategyState.MakerProcess; break; case StrategyState.MakerProcess: COrder order = DctLegToOrder[MakerLeg]; if (order.Status.Equals(COrder.OrderState.Filled)) { State = StrategyState.TakerSend; goto case StrategyState.TakerSend; } else if (Profit < profitUSD && order.canCancel()) { order.cancel(); State = Continuous ? StrategyState.Continuous : StrategyState.Active; DctLegToOrder.Clear(); } break; case StrategyState.TakerSend: for (int currentLeg = 1; currentLeg <= dctLegs.Count; currentLeg++) { if (!DctLegToOrder.ContainsKey(currentLeg)) { OrderSide sideTaker = dctLegs[currentLeg].Item1; CProduct productTaker = dctLegs[currentLeg].Item2; Double sizeTaker = GetSize(sideTaker, productTaker); Double priceTaker = ((Double)productTaker.Bid + (Double)productTaker.Ask) / 2.0; CurrentLeg = currentLeg; dctLegs[currentLeg].Item2.Exchange.trade(this, currentLeg, sideTaker, productTaker, Math.Round(sizeTaker, productTaker.PrecisionSize), Math.Round(priceTaker, productTaker.PrecisionPrice)); } } if (DctLegToOrder.Count >= 3) { State = StrategyState.TakerProcess; } break; case StrategyState.TakerProcess: Boolean allFilled = true; for (int currentLeg = 1; currentLeg <= dctLegs.Count; currentLeg++) { if (DctLegToOrder.ContainsKey(currentLeg)) { COrder orderTaker = DctLegToOrder[currentLeg]; if (orderTaker.Status.Equals(COrder.OrderState.Sent) || orderTaker.Status.Equals(COrder.OrderState.Cancelled)) { allFilled = false; } else if (orderTaker.canCancel()) { allFilled = false; CExchange exchange = orderTaker.Exchange; OrderSide sideTaker = orderTaker.Side; CProduct productTaker = orderTaker.Product; Double sizeTaker = orderTaker.Size; Double priceTaker = ((Double)productTaker.Bid + (Double)productTaker.Ask) / 2.0; CurrentLeg = currentLeg; orderTaker.cancel(); COrder orderCancel; DctLegToOrder.TryRemove(currentLeg, out orderCancel); exchange.trade(this, currentLeg, sideTaker, productTaker, Math.Round(sizeTaker, productTaker.PrecisionSize), Math.Round(priceTaker, productTaker.PrecisionPrice)); } } else { allFilled = false; } } if (allFilled) { if (Continuous) { State = StrategyState.Continuous; } else { State = StrategyState.Inactive; } DctLegToOrder.Clear(); } break; } } catch (Exception ex) { server.AddLog(ex.Message); } processStrategy = false; }
public CStrategyServer(string[] args) { Server = this; IsActive = true; TradeUSD = 1.0; MinProfit = 0.002; dctExchanges = new Dictionary <String, CExchange>(); CExchange kuExchange = new CKuCoin(); dctExchanges.Add(kuExchange.Name, kuExchange); CExchange beExchange = new CBinance(); dctExchanges.Add(beExchange.Name, beExchange); CExchange gdaxExchange = new CGDAX(); dctExchanges.Add(gdaxExchange.Name, gdaxExchange); colServerProducts = new MTObservableCollection <CProduct>(); dctServerProducts = new Dictionary <String, CProduct>(); colStrategies = new MTObservableCollection <CTriArb>(); CExchange exchangeConfig; // load yaml config string config = File.ReadAllText(args[0]); // load Yaml var input = new StringReader(config); // Load the stream var yaml = new YamlStream(); yaml.Load(input); // Examine the stream var mapping = (YamlMappingNode)yaml.Documents[0].RootNode; foreach (var entry in mapping.Children) { if (entry.Key.ToString().Equals("Exchanges")) { foreach (YamlMappingNode exchangeYaml in ((YamlSequenceNode)entry.Value).Children) { exchangeConfig = dctExchanges[exchangeYaml["Exchange"].ToString()]; var productsYaml = (YamlSequenceNode)exchangeYaml["Products"]; foreach (YamlMappingNode productYaml in productsYaml) { String symbol = productYaml.Children[new YamlScalarNode("symbol")].ToString(); int precisionSize = int.Parse(productYaml.Children[new YamlScalarNode("precisionSize")].ToString()); int precisionPrice = int.Parse(productYaml.Children[new YamlScalarNode("precisionPrice")].ToString()); CProduct productConfig = new CProduct(exchangeConfig, symbol, precisionSize, precisionPrice); dctServerProducts.Add(exchangeConfig + "." + symbol, productConfig); if (symbol.Contains("USD")) { colServerProducts.Add(productConfig); } productConfig.Exchange.dctExchangeProducts.Add(symbol, productConfig); } var strategiesYaml = (YamlSequenceNode)exchangeYaml["Strategies"]; foreach (YamlMappingNode strategyYaml in strategiesYaml) { Dictionary <int, Tuple <OrderSide, CProduct> > dctLegs_config = new Dictionary <int, Tuple <OrderSide, CProduct> >(); for (int leg = 1; leg <= 3; leg++) { String legsymbol = strategyYaml.Children[new YamlScalarNode("leg" + leg + "symbol")].ToString(); CProduct strategyProduct = dctServerProducts[exchangeConfig + "." + legsymbol]; Enum.TryParse(strategyYaml.Children[new YamlScalarNode("leg" + leg + "side")].ToString(), out OrderSide orderSide); dctLegs_config.Add(leg, new Tuple <OrderSide, CProduct>(orderSide, strategyProduct)); } int makerLeg = int.Parse(strategyYaml.Children[new YamlScalarNode("makerleg")].ToString()); colStrategies.Add(new CTriArb(dctLegs_config, makerLeg)); } } } } colServerOrders = new MTObservableCollection <COrder>(); dctIdToOrder = new ConcurrentDictionary <String, COrder>(); System.Timers.Timer timerTicks = new System.Timers.Timer(5000); timerTicks.Elapsed += new ElapsedEventHandler(pollTicks); timerTicks.Start(); System.Timers.Timer timerOrders = new System.Timers.Timer(5000); timerOrders.Elapsed += new ElapsedEventHandler(pollOrders); timerOrders.Start(); System.Timers.Timer timerPositions = new System.Timers.Timer(5000); timerPositions.Elapsed += new ElapsedEventHandler(pollPositions); timerPositions.Start(); System.Timers.Timer timerStrategy = new System.Timers.Timer(5000); timerStrategy.Elapsed += new ElapsedEventHandler(cycleStrategy); timerStrategy.Start(); openGui(); }
public override async void trade(CStrategy strategy, int?leg, OrderSide?side, CProduct product, Double size, Double price) { try { String endpoint = "/v1/order"; Dictionary <string, string> parameters = new Dictionary <string, string> { { "amount", size.ToString() }, { "price", price.ToString() }, { "symbol", product.Symbol }, { "type", side.GetValueOrDefault().ToString().ToUpper() } }; HttpRequestMessage requestMessage = KuCoinPrivate(endpoint, parameters, HttpMethod.Post); // Create a client HttpClient httpClient = new HttpClient(); // Send the request to the server HttpResponseMessage response = await httpClient.SendAsync(requestMessage); // get json back string json = await response.Content.ReadAsStringAsync(); // parse order String dynamic orderData = JsonConvert.DeserializeObject(json); String orderID; try { orderID = orderData.data.orderOid; } catch (Exception ex) { server.AddLog(ex.Message); orderID = ""; } if (!orderID.Equals("")) { COrder order = new COrder(orderID); order.Product = product; order.Side = side.GetValueOrDefault(); order.Size = size; order.Price = price; String orderStatus = orderData.msg.ToString(); if (orderStatus.Equals("OK") || orderStatus.Equals("Sent")) { order.Status = COrder.OrderState.Sent; } else { order.Status = COrder.OrderState.Unknown; } order.Strategy = strategy; order.Exchange = this; Double timeStamp = orderData.timestamp; order.TimeStampSent = CHelper.ConvertFromUnixTimestamp(timeStamp); server.AddLog("Created Order " + this.Name + " " + orderID + " " + product + " " + side + " " + size + " " + price); // add order to global Orders server.colServerOrders.Add(order); server.dctIdToOrder[orderID] = order; // add order to strategy orders strategy.DctStrategyOrders[orderID] = order; if (leg != null) { strategy.DctLegToOrder[(int)leg] = order; } // cleanup order.updateGUI(); server.AddLog(json); } } catch (Exception ex) { server.AddLog(ex.Message); } }
public override async void pollPositions(object source, ElapsedEventArgs e) { if (pollingPositions) { return; } else { pollingPositions = true; } HttpClient httpClient = new HttpClient(); try { String endpoint; Dictionary <string, string> parameters; endpoint = "/v1/account/balances"; int totalPage = 99; int currentPage = 0; int limit = 12; while (++currentPage <= totalPage) { parameters = new Dictionary <string, string> { { "limit", limit.ToString() }, { "page", currentPage.ToString() }, }; HttpRequestMessage requestMessage = KuCoinPrivate(endpoint, parameters, HttpMethod.Get); // Send the request to the server HttpResponseMessage response = await httpClient.SendAsync(requestMessage); // Just as an example I'm turning the response into a string here string json = await response.Content.ReadAsStringAsync(); dynamic balanceData = JsonConvert.DeserializeObject(json); var numTicks = balanceData.timestamp; var posixTime = DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc); //var time = posixTime.AddMilliseconds(numTicks); var balances = balanceData.data; if (balances != null) { var total = balances.total; var pageNos = balances.pageNos; int.TryParse(pageNos.ToString(), out totalPage); foreach (var pos in balances.datas) { var coinType = pos.coinType; var balance = pos.balance; var freezeBalance = pos.freezeBalance; String symbol = exchangeUSD(coinType.ToString()); if (dctExchangeProducts.ContainsKey(symbol)) { CProduct product = dctExchangeProducts[symbol]; product.TimeStampLastBalance = DateTime.Now; Double dbal = 0; Double.TryParse(balance.ToString(), out dbal); Double dfreezeBal = 0; Double.TryParse(freezeBalance.ToString(), out dfreezeBal); if (product.CurrentBalance.HasValue && dbal != product.CurrentBalance.GetValueOrDefault()) { server.AddLog("Balance Changed!"); } product.SetBalance(dbal + dfreezeBal); product.updateGUI(); } } } } } catch (Exception ex) { server.AddLog(ex.Message); } pollingPositions = false; }
public abstract void trade(CStrategy strategy, int?leg, OrderSide?side, CProduct product, Double size, Double price);