public TradingResult OnTradingResult(AccountInfo account, Ticker ticker, string text) { try { JObject obj = JsonConvert.DeserializeObject <JObject>(text); JObject error = obj.Value <JObject>("error"); if (error != null) { LogManager.Default.Error(this, "trade", error.Value <string>("message")); return(null); } TradingResult res = new TradingResult(); res.OrderId = obj.Value <string>("orderID"); res.Date = Convert.ToDateTime(obj.Value <string>("transactTime")); res.Amount = FastValueConverter.Convert(obj.Value <string>("orderQty")); res.Type = obj.Value <string>("side")[0] == 'B' ? OrderType.Buy : OrderType.Sell; res.Value = FastValueConverter.Convert(obj.Value <string>("price")); res.OrderStatus = obj.Value <string>("ordStatus"); res.Filled = res.OrderStatus == "Filled"; res.Total = res.Amount; return(res); } catch (Exception e) { Telemetry.Default.TrackException(e); return(null); } }
public TradingResult OnSell(AccountInfo account, Ticker ticker, string result) { string res = OnUuidResult(result); TradingResult t = new TradingResult(); t.Trades.Add(new TradeEntry() { Id = res }); return(t); }
public async Task <TradingResult> TradeAsync() { TradingResult result = null; foreach (var traderRule in _traderRules) { result = await traderRule.ExecuteAsync(this); } return(result); }
protected virtual OpenPositionInfo OpenShortPosition(Ticker ticker, string mark, double value, double amount, bool allowTrailing, bool checkForMinValue, double trailingStopLossPc, double minProfitPc) { double spent = ticker.SpentInBaseCurrency(value, amount); if (1.05 * spent > GetMaxAllowedShortDeposit()) { return(null); } if (checkForMinValue && spent < MinDepositForOpenPosition) { return(null); } TradingResult res = MarketSell(ticker, value, amount); if (res == null) { return(null); } OpenPositionInfo info = new OpenPositionInfo() { Ticker = ticker, DataItemIndex = StrategyData.Count - 1, Time = DataProvider.CurrentTime, Type = OrderType.Sell, Spent = spent + CalcFee(res.Total), AllowTrailing = allowTrailing, StopLossPercent = trailingStopLossPc, OpenValue = res.Value, OpenAmount = res.Amount, Amount = res.Amount, Mark = mark, AllowHistory = (DataProvider is SimulationStrategyDataProvider), Total = res.Total, MinProfitPercent = minProfitPc, CloseValue = value * (1 + minProfitPc * 0.01), }; info.UpdateCurrentValue(DataProvider.CurrentTime, res.Value); OpenedOrders.Add(info); OrdersHistory.Add(info); OnOpenShortPosition(info); UpdateMaxAllowedShortDeposit(-info.Spent); IOpenedPositionsProvider provider = (IOpenedPositionsProvider)StrategyData.Last(); provider.OpenedPositions.Add(info); provider.AddMark(mark); Save(); return(info); }
private static void ClientShowErrorNotification( TradingStationLot lot, TradingResult error, bool isPlayerBuying) { var message = error.GetDescription(); if (error == TradingResult.ErrorNotEnoughMoneyOnPlayer) { // calculate how many coins are needed var character = Client.Characters.CurrentPlayerCharacter; long deficitShiny = 0, deficitPenny = 0; if (lot.PriceCoinShiny > 0) { deficitShiny = lot.PriceCoinShiny - character.CountItemsOfType(ProtoItemCoinShiny.Value); } if (lot.PriceCoinPenny > 0) { deficitPenny = lot.PriceCoinPenny - character.CountItemsOfType(ProtoItemCoinPenny.Value); } if (deficitShiny > 0 || deficitPenny > 0) { if (deficitShiny > 0) { // ReSharper disable once CanExtractXamlLocalizableStringCSharp message += "[br]" + string.Format(NotificationNeedMoreShinyCoins, deficitShiny); } if (deficitPenny > 0) { // ReSharper disable once CanExtractXamlLocalizableStringCSharp message += "[br]" + string.Format(NotificationNeedMorePennyCoins, deficitPenny); } } } NotificationSystem.ClientShowNotification( isPlayerBuying ? NotiticationCannotBuy_Title : NotiticationCannotSell_Title, message, NotificationColor.Bad, icon: lot.ProtoItem.Icon); }
private void RaiseOnTrade(TradingResult trade) { TradeEventHandler handler = (TradeEventHandler)Events[onTrade]; if (handler != null) { handler(this, new TradeEventArgs() { Trade = trade }); } }
private static void ClientShowErrorNotification( TradingStationLot lot, TradingResult error, bool isPlayerBuying) { var message = error.GetDescription(); if (error == TradingResult.ErrorNotEnoughMoneyOnPlayer) { // calculate how many coins are needed long shinyNotEnough = 0, pennyNotEnough = 0; if (lot.PriceCoinShiny > 0) { shinyNotEnough = lot.PriceCoinShiny - Client.Characters.CurrentPlayerCharacter.CountItemsOfType( ProtoItemCoinShiny.Value); } if (lot.PriceCoinPenny > 0) { pennyNotEnough = lot.PriceCoinPenny - Client.Characters.CurrentPlayerCharacter.CountItemsOfType( ProtoItemCoinPenny.Value); } if (shinyNotEnough > 0 || pennyNotEnough > 0) { if (shinyNotEnough > 0) { message += Environment.NewLine + string.Format(NotificationNeedMoreShinyCoins, shinyNotEnough); } if (pennyNotEnough > 0) { message += Environment.NewLine + string.Format(NotificationNeedMorePennyCoins, pennyNotEnough); } } } NotificationSystem.ClientShowNotification( isPlayerBuying ? NotiticationCannotBuy_Title : NotiticationCannotSell_Title, message, NotificationColor.Bad, icon: lot.ProtoItem.Icon); }
protected TradingResult AddDemoTradingResult(Ticker ticker, double rate, double amount, OrderType type) { TradingResult res = new TradingResult() { Amount = amount, Type = type, Date = DateTime.Now, OrderId = "demo", Total = rate * amount }; res.Value = rate; res.Trades.Add(new TradeEntry() { Ticker = ticker, Amount = amount, Date = DateTime.Now, Id = "demo", Rate = rate, Total = rate * amount, Type = type }); return(res); }
protected virtual OpenPositionInfo OpenLongPosition(string mark, double value, double amount, bool allowTrailing, bool checkForMinValue, double trailingStopLossPc, double minProfitPc) { if (1.05 * value * amount > MaxAllowedDeposit) { return(null); } if (checkForMinValue && value * amount < MinDepositForOpenPosition) { return(null); } TradingResult res = MarketBuy(value, amount); if (res == null) { return(null); } OpenPositionInfo info = new OpenPositionInfo() { DataItemIndex = StrategyData.Count - 1, Time = DataProvider.CurrentTime, Type = OrderType.Buy, Spent = res.Total + CalcFee(res.Total), AllowTrailing = allowTrailing, StopLossPercent = trailingStopLossPc, OpenValue = res.Value, OpenAmount = res.Amount, Amount = res.Amount, Mark = mark, AllowHistory = (DataProvider is SimulationStrategyDataProvider), Total = res.Total, MinProfitPercent = minProfitPc, CloseValue = value * (1 + minProfitPc * 0.01), }; info.UpdateCurrentValue(DataProvider.CurrentTime, res.Value); OpenedOrders.Add(info); OrdersHistory.Add(info); OnOpenLongPosition(info); MaxAllowedDeposit -= info.Spent; IOpenedPositionsProvider provider = (CombinedStrategyDataItem)StrategyData.Last(); provider.OpenedPositions.Add(info); provider.AddMark(mark); Save(); return(info); }
protected void Sell() { OrderBookEntry e = GetAvailableToSell(SellLevel); TradingResult res = MarketSell(e.Value, e.Amount); if (res == null) { return; } SoldTotal += res.Amount; Earned += res.Total - CalcFee(res.Total); MaxActualBuyDeposit += res.Total; MaxActualSellDeposit -= res.Amount + CalcFee(res.Total); }
protected void Buy() { OrderBookEntry e = GetAvailableToBuy(BuyLevel); TradingResult res = MarketBuy(e.Value, e.Amount); if (res == null) { return; } BoughtTotal += res.Total; Earned -= res.Total + CalcFee(res.Total); MaxActualBuyDeposit -= res.Total + CalcFee(res.Total); MaxActualSellDeposit += res.Amount; }
protected override TradingResult OnTradeResultCore(AccountInfo account, Ticker ticker, JObject res) { TradingResult tr = new TradingResult(); tr.Ticker = ticker; tr.OrderId = res.Value <string>("orderId"); tr.Amount = Convert.ToDouble(res.Value <string>("executedQty")); tr.Value = Convert.ToDouble(res.Value <string>("price")); tr.Type = res.Value <string>("side")[0] == 'B'? OrderType.Buy: OrderType.Sell; tr.PositionSide = String2PositionSide(res.Value <string>("positionSide")); tr.Total = tr.Amount * tr.Value; tr.OrderStatus = res.Value <string>("status"); tr.Filled = res.Value <bool>("closePosition") == true; return(tr); }
protected void CloseShortPosition(OpenPositionInfo info, TradingResult res) { if (res == null) { return; } double earned = res.Total - CalcFee(res.Total); MaxAllowedShortDeposit += earned; info.UpdateCurrentValue(DataProvider.CurrentTime, res.Value); info.Earned += earned; info.Amount -= res.Amount; info.Total -= res.Total; info.CloseValue = res.Value; //CombinedStrategyDataItem item = (CombinedStrategyDataItem)StrategyData.FirstOrDefault(i => ((CombinedStrategyDataItem)i).Time == info.CandlestickTime); //if(item != null) { // item.Closed = true; // item.CloseLength = ((CombinedStrategyDataItem)StrategyData.Last()).Index - item.Index; //} IOpenedPositionsProvider last = (IOpenedPositionsProvider)StrategyData.Last(); double fee = 0.075 / 100.0; double profit = ((1 / info.CloseValue) - (1 / info.OpenValue)) * res.Amount; double openFee = fee * (1 / info.OpenValue) * res.Amount; // info.Ticker.Total(info.OpenValue, res.Amount); double closeFee = fee * (1 / info.CloseValue) * res.Amount; // info.Ticker.Total(info.CloseValue, res.Amount); profit -= openFee + closeFee; profit *= Short.UsdTicker.OrderBook.Bids[0].Value; Earned += profit; if (info.Amount < 0.000001) { OpenedOrders.Remove(info); last.ClosedPositions.Add(info); info.CloseTime = DataProvider.CurrentTime; } //last.ClosedOrder = true; //last.Value = Ticker.OrderBook.Bids[0].Value; //if(item != null) // item.Profit = profit; //last.AddMark("Close " + info.Mark); }
protected virtual TradingResult PlaceAsk(double rate, double amount) { TradingResult res = null; if (!DemoMode) { res = Ticker.Sell(rate, amount); if (res == null) { Log(LogType.Error, "", rate, amount, StrategyOperation.LimitSell); } return(res); } else { res = AddDemoTradingResult(rate, amount, OrderType.Sell); } Log(LogType.Error, "", rate, amount, StrategyOperation.LimitSell); return(res); }
protected virtual TradingResult MarketSell(double rate, double amount) { TradingResult res = null; if (!DemoMode) { res = Ticker.Sell(rate, amount); if (res == null) { Log(LogType.Error, "", rate, amount, StrategyOperation.MarketSell); } return(res); } else { res = AddDemoTradingResult(rate, amount, OrderType.Sell); } TradeHistory.Add(res); Log(LogType.Success, "", rate, amount, StrategyOperation.MarketSell); return(res); }
protected TradingResult OnTradeResult(AccountInfo account, Ticker ticker, byte[] data) { if (data == null) { return(null); } string text = Encoding.UTF8.GetString(data); JObject res = JsonConvert.DeserializeObject <JObject>(text); if (res.Value <string>("code") != null) { LogManager.Default.Error(this, "trade", text); return(null); } TradingResult tr = new TradingResult(); tr.OrderId = res.Value <string>("orderId"); tr.Amount = Convert.ToDouble(res.Value <string>("executedQty")); tr.Value = Convert.ToDouble(res.Value <string>("price")); tr.Total = tr.Amount * tr.Value; tr.OrderStatus = res.Value <string>("status"); tr.Filled = tr.OrderStatus == "FILLED"; JArray fills = res.Value <JArray>("fills"); if (fills == null) { return(tr); } foreach (JObject item in fills) { TradeEntry e = new TradeEntry(); e.Amount = Convert.ToDouble(item.Value <string>("qty")); e.Rate = Convert.ToDouble(item.Value <string>("price")); e.Fee = Convert.ToDouble(item.Value <string>("comission")); e.FeeAsset = item.Value <string>("commissionAsset"); tr.Trades.Add(e); } return(tr); }
protected void CloseLongPosition(OpenPositionInfo info, TradingResult res) { if (res == null) { return; } double earned = res.Total - CalcFee(res.Total); MaxAllowedDeposit += earned; info.UpdateCurrentValue(DataProvider.CurrentTime, res.Value); info.Earned += earned; info.Amount -= res.Amount; info.Total -= res.Total; info.CloseValue = res.Value; //StatisticalArbitrageHistoryItem item = (StatisticalArbitrageHistoryItem)StrategyData.FirstOrDefault(i => ((StatisticalArbitrageHistoryItem)i).Time == info.CandlestickTime); //if(item != null) { // item.Closed = true; // item.CloseLength = ((CombinedStrategyDataItem)StrategyData.Last()).Index - item.Index; //} IOpenedPositionsProvider last = StrategyData.Last() as IOpenedPositionsProvider; if (info.Amount < 0.000001) { OpenedOrders.Remove(info); last.ClosedPositions.Add(info); info.CloseTime = DataProvider.CurrentTime; Earned += info.Earned - info.Spent; } //last.ClosedOrder = true; //last.Value = Ticker.OrderBook.Bids[0].Value; //if(item != null) // item.Profit = earned - info.Spent; //last.AddMark("Close " + info.Mark); }
protected override void CloseLongPosition(OpenPositionInfo info) { TradingResult res = MarketSell(Ticker.OrderBook.Bids[0].Value, info.Amount); if (res != null) { double earned = res.Total - CalcFee(res.Total); MaxAllowedDeposit += earned; info.UpdateCurrentValue(DataProvider.CurrentTime, res.Value); info.Earned += earned; info.Amount -= res.Amount; info.Total -= res.Total; info.CloseValue = res.Value; CombinedStrategyDataItem item = (CombinedStrategyDataItem)StrategyData.FirstOrDefault(i => ((CombinedStrategyDataItem)i).Time == info.CandlestickTime); if (item != null) { item.Closed = true; item.CloseLength = ((CombinedStrategyDataItem)StrategyData.Last()).Index - item.Index; } CombinedStrategyDataItem last = (CombinedStrategyDataItem)StrategyData.Last(); if (info.Amount < 0.000001) { OpenedOrders.Remove(info); last.ClosedPositions.Add(info); info.CloseTime = DataProvider.CurrentTime; Earned += info.Earned - info.Spent; } last.ClosedOrder = true; last.Value = Ticker.OrderBook.Bids[0].Value; if (item != null) { item.Profit = earned - info.Spent; } last.AddMark("Close " + info.Mark); } }
private void MakeTrade(OrderType type) { if (!ValidateChildrenCore()) { XtraMessageBox.Show("Not all fields are filled!"); return; } string validationError = string.Empty; if (type == OrderType.Buy) { validationError = Ticker.ValidateTrade(Settings.BuyPrice, Settings.BuyAmount); } else { validationError = Ticker.ValidateTrade(Settings.SellPrice, Settings.SellAmount); } if (!string.IsNullOrEmpty(validationError)) { XtraMessageBox.Show("Error validating trade. Values will be corrected. Error was: " + validationError); double rate = 0; double amount = 0; if (type == OrderType.Buy) { rate = Settings.BuyPrice; amount = Settings.BuyAmount; } else { rate = Settings.SellPrice; amount = Settings.SellAmount; } Ticker.CorrectTrade(ref rate, ref amount); if (type == OrderType.Buy) { Settings.BuyPrice = rate; Settings.BuyAmount = amount; } else { Settings.SellPrice = rate; Settings.SellAmount = amount; } return; } TradingResult res = null; if (type == OrderType.Buy) { res = Ticker.Buy(Settings.BuyPrice, Settings.BuyAmount); if (res == null) { XtraMessageBox.Show("Error buying. " + LogManager.Default.Messages.Last().Description); return; } } else { Settings.Enabled = false; res = Ticker.Sell(Settings.SellPrice, Settings.SellAmount); if (res == null) { XtraMessageBox.Show("Error selling. " + LogManager.Default.Messages.Last().Description); return; } } TradingResult = res; if (Settings.Enabled) { Settings.Date = DateTime.UtcNow; Ticker.Trailings.Add(Settings); Settings.Start(); if (OperationsProvider != null) { OperationsProvider.ShowTradingResult(Ticker); } Ticker.Save(); XtraMessageBox.Show("Trailing added!"); } RaiseOnTrade(res); }
private bool SharedValidateCanTrade( IStaticWorldObject tradingStation, TradingStationLot lot, TradingStationMode mode, ICharacter character, out TradingResult error) { var protoTradingStation = tradingStation.ProtoStaticWorldObject; var publicState = GetPublicState(tradingStation); if (publicState.Mode != mode) { throw new Exception("Trading station has different trading mode"); } if (!protoTradingStation .SharedCanInteract(character, tradingStation, writeToLog: false)) { error = TradingResult.ErrorCannotInteract; return(false); } var lots = publicState.Lots; var isLotFound = false; foreach (var otherLot in lots) { if (otherLot == lot) { // found lot isLotFound = true; break; } } if (!isLotFound) { error = TradingResult.ErrorLotNotFound; return(false); } if (lot.State == TradingStationLotState.Disabled) { error = TradingResult.ErrorLotNotActive; return(false); } if (mode == TradingStationMode.StationBuying) { // ensure that the character has required item count to sell if (lot.LotQuantity > character.CountItemsOfType(lot.ProtoItem)) { error = TradingResult.ErrorNotEnoughItemsOnPlayer; return(false); } if (IsServer) { // ensure station has enough money to pay for these items var tradingStationItemsContainer = GetPrivateState(tradingStation).StockItemsContainer; if (!tradingStationItemsContainer.ContainsItemsOfType( ProtoItemCoinPenny.Value, requiredCount: lot.PriceCoinPenny) || !tradingStationItemsContainer.ContainsItemsOfType( ProtoItemCoinShiny.Value, requiredCount: lot.PriceCoinShiny)) { error = TradingResult.ErrorNotEnoughMoneyOnStation; return(false); } } } else // if station selling { if (lot.CountAvailable == 0) { error = TradingResult.ErrorNotEnoughItemsOnStation; return(false); } // ensure player has enough money to pay for these items if (!character.ContainsItemsOfType( ProtoItemCoinPenny.Value, requiredCount: lot.PriceCoinPenny) || !character.ContainsItemsOfType( ProtoItemCoinShiny.Value, requiredCount: lot.PriceCoinShiny)) { error = TradingResult.ErrorNotEnoughMoneyOnPlayer; return(false); } } // no error error = TradingResult.Success; return(true); }
private bool TryCloseDeals(double bottomBid, double topAsk, double spreadToClose) { if (spreadToClose > SpreadClosePosition) { return(false); } if (OpenedOrders.Count == 0) { return(false); } //StatisticalArbitrageOrderInfo order = GetOpenedOrderWithMaxSpread(); foreach (StatisticalArbitrageOrderInfo order in OpenedPairs) { if (order.Spread < SpreadClosePosition) { continue; } double actualLongCloseBid = Long.GetActualBidByAmount(order.LongAmount); double actualShortCloseAsk = Short.GetActualAskByAmount(order.ShortAmount); double spread = actualShortCloseAsk - actualLongCloseBid; if (spread > SpreadClosePosition) { continue; } double actualSellAmount = GetActualBottomBidAmount(actualLongCloseBid); double actualBuyAmount = GetActualShortAskAmount(actualShortCloseAsk); double finalSellAmount = Math.Min(actualSellAmount, order.LongAmount); double koeffSell = finalSellAmount / order.LongAmount; double finalBuyAmount = Math.Min(actualBuyAmount, order.ShortAmount); double koeffBuy = finalBuyAmount / order.ShortAmount; double koeff = Math.Min(koeffBuy, koeffSell); finalSellAmount *= koeff; finalBuyAmount *= koeff; TradingResult closeLong = MarketSell(Long, bottomBid, finalSellAmount); TradingResult closeShort = MarketBuy(Short, topAsk, finalBuyAmount); order.LongAmount -= closeLong.Amount; order.ShortAmount -= closeShort.Amount; //double eInc = (1 / order.LongValue - 1 / order.ShortValue) * finalBuyAmount; //Earned += eInc; LastItem = new StatisticalArbitrageHistoryItem(); LastItem.Time = DataProvider.CurrentTime; LastItem.Earned = Earned; LastItem.LongAmount = finalSellAmount; LastItem.LongAsk = Long.OrderBook.LowestAsk; LastItem.LongBid = bottomBid; LastItem.ShortAsk = topAsk; LastItem.ShortBid = Short.OrderBook.HighestBid; LastItem.ShortAmount = finalBuyAmount; LastItem.Close = true; LastItem.Index = StrategyData.Count; LastItem.Mark = "CLOSE"; LastItem.ClosedPositions.Add(order.LongPosition); LastItem.ClosedPositions.Add(order.ShortPosition); StrategyData.Add(LastItem); CloseLongPosition(order.LongPosition, closeLong); CloseShortPosition(order.ShortPosition, closeShort); if (order.LongAmount <= 0 && order.ShortAmount <= 0) { OpenedPairs.Remove(order); OnOrderClosed(LastItem); } else { throw new Exception("Partial Close Not Implemented"); } } return(true); }