public static void TrailStops(this BotBase bot, PositionDouble position, double newExtreme, double trailAmount) { if (trailAmount <= 0) { return; } if (position.TradeType == TradeType.Buy) { var trailPrice = newExtreme - trailAmount; if (!position.StopLoss.HasValue || trailPrice > position.StopLoss.Value) { bot.ModifyPosition(position, trailPrice, position.TakeProfit); } } else { var trailPrice = newExtreme + trailAmount; if (!position.StopLoss.HasValue || trailPrice < position.StopLoss.Value) { bot.ModifyPosition(position, trailPrice, position.TakeProfit); } } }
public override TradeResult ModifyPosition(PositionDouble position, double?stopLoss, double?takeProfit) { throw new NotImplementedException(); }
public override TradeResult ClosePosition(PositionDouble position) { throw new NotImplementedException(); }
public override TradeResult ModifyPosition(PositionDouble position, double?stopLoss, double?takeProfit) { logger.LogError($"NOT IMPLEMENTED: ModifyPosition {position.Id} sl:{stopLoss} tp:{takeProfit}"); return(TradeResult.NotImplemented); }
public override TradeResult ClosePosition(PositionDouble position) { logger.LogError($"NOT IMPLEMENTED: ClosePosition {position.Id}"); return(TradeResult.NotImplemented); }
public static readonly int PositionsPageSize = 500; // HARDCONST REVIEW public async static Task <List <PositionDouble> > GetPositions(CTraderAccount account) { again: List <PositionDouble> Result = new List <PositionDouble>(); var apiInfo = Defaults.TryGet <ISpotwareConnectAppInfo>(); var client = NewHttpClient(); var uri = SpotwareAccountApi.PositionsUri; uri = uri .Replace("{id}", account.Template.AccountId) .Replace("{access_token}", System.Uri.EscapeDataString(account.Template.AccessToken)) .Replace("{limit}", PositionsPageSize.ToString()) // TODO: Paging if there are more positions, and cache ; //UpdateProgress(0.11, "Sending request"); var response = await client.GetAsyncWithRetries(uri).ConfigureAwait(false); //UpdateProgress(0.12, "Receiving response"); var receiveStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); System.IO.StreamReader readStream = new System.IO.StreamReader(receiveStream, System.Text.Encoding.UTF8); var json = readStream.ReadToEnd(); //UpdateProgress(0.95, "Deserializing"); //var error = Newtonsoft.Json.JsonConvert.DeserializeObject<SpotwareErrorContainer>(json); //if (error?.error != null) //{ // throw new Exception($"API returned error: {error.error.errorCode} - '{error.error.description}'"); //} var data = Newtonsoft.Json.JsonConvert.DeserializeObject <SpotwarePositionsResult>(json); //UpdateProgress(0.98, "Processing data"); if (data?.data != null) { foreach (var pos in data.data) { var position = new PositionDouble() { Id = pos.positionId, EntryPrice = pos.entryPrice, EntryTime = pos.entryTimestamp.ToDateTime(), GrossProfit = pos.profit, Label = pos.label, Pips = pos.profitInPips, StopLoss = pos.stopLoss, Swap = pos.swap, TakeProfit = pos.takeProfit, TradeType = pos.tradeSide.ToTradeType(), Volume = pos.volume, SymbolCode = pos.symbolName, Symbol = account.GetSymbol(pos.symbolName), Commissions = pos.commission, Comment = pos.comment, }; Result.Add(position); } } else { var error = Newtonsoft.Json.JsonConvert.DeserializeObject <SpotwareErrorContainer>(json); if (json.Contains("CH_ACCESS_TOKEN_INVALID")) { // TODO: Refactor to a reusable place bool renewResult = await TryRenewToken(account); if (renewResult) { goto again; } else { throw new AccessTokenInvalidException(); } } else { throw new Exception("GetPositions: got no data from json response: " + json); } } //UpdateProgress(1, "Done"); return(Result); }
public async static Task <List <PositionDouble> > GetHistoricalPositions(long accountId, string accessToken, IAccount market) { List <PositionDouble> Result = new List <PositionDouble>(); var apiInfo = Defaults.TryGet <ISpotwareConnectAppInfo>(); var client = NewHttpClient(); var uri = SpotwareAccountApi.PositionsUri; uri = uri .Replace("{id}", accountId.ToString()) .Replace("{access_token}", accessToken) .Replace("{limit}", "10000") // HARDCODE REVIEW ; //UpdateProgress(0.11, "Sending request"); var response = await client.GetAsync(uri).ConfigureAwait(false); //UpdateProgress(0.12, "Receiving response"); var receiveStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); System.IO.StreamReader readStream = new System.IO.StreamReader(receiveStream, System.Text.Encoding.UTF8); var json = readStream.ReadToEnd(); //UpdateProgress(0.95, "Deserializing"); //var error = Newtonsoft.Json.JsonConvert.DeserializeObject<SpotwareErrorContainer>(json); //if (error?.error != null) //{ // throw new Exception($"API returned error: {error.error.errorCode} - '{error.error.description}'"); //} var data = Newtonsoft.Json.JsonConvert.DeserializeObject <SpotwareDealsResult>(json); //UpdateProgress(0.98, "Processing data"); if (data.data != null) { foreach (var pos in data.data) { TradeType tradeType; var tradeSide = pos.tradeSide.Trim('"'); if (tradeSide == "SELL") { tradeType = TradeType.Sell; } else if (tradeSide == "BUY") { tradeType = TradeType.Buy; } else { throw new Exception("Invalid tradeSide from server: " + pos.tradeSide); } var position = new PositionDouble() { Id = pos.positionId, OrderId = pos.orderId, DealId = pos.dealId, TradeType = tradeType, Volume = pos.volume, FilledVolume = pos.filledVolume, SymbolCode = pos.symbolName, Symbol = market.GetSymbol(pos.symbolName), Commissions = pos.commission, EntryPrice = pos.executionPrice, EntryTime = pos.executionTimestamp.ToDateTime(), CreateTime = pos.createTimestamp.ToDateTime(), Comment = pos.comment, }; if (pos.positionCloseDetails != null) { position.CloseDetails = new PositionCloseDetails() { Balance = pos.positionCloseDetails.balance, ClosedVolume = pos.positionCloseDetails.closedVolume, Comment = pos.positionCloseDetails.comment, Commission = pos.positionCloseDetails.commission, EntryPrice = pos.positionCloseDetails.entryPrice, Equity = pos.positionCloseDetails.equity, EquityBasedRoi = pos.positionCloseDetails.equityBasedRoi, Profit = pos.positionCloseDetails.profit, ProfitInPips = pos.positionCloseDetails.profitInPips, QuoteToDepositConversionRate = pos.positionCloseDetails.quoteToDepositConversionRate, Roi = pos.positionCloseDetails.roi, StopLossPrice = pos.positionCloseDetails.stopLossPrice, Swap = pos.positionCloseDetails.swap, TakeProfitPrice = pos.positionCloseDetails.takeProfitPrice, }; } Result.Add(position); } } //UpdateProgress(1, "Done"); return(Result); }