/// <summary> /// Get all connections for a specific user /// </summary> /// <param name="userId">Id of the user to get the connection for</param> /// <returns>An enumerable collection of the connections</returns> public async Task <IEnumerable <Contracts.Connection.Connection> > GetConnectionsForUser(Guid userId) { // Collect connections var connectionsInDb = GetConnectionsForUserFromDb(userId); var connections = _mapper.Map <IEnumerable <Contracts.Connection.Connection> >(connectionsInDb); // Collect open trades for them foreach (var conn in connections) { // Oanda if (conn.Broker == Database.Connection.Broker.Oanda) { var oandaServer = conn.Type == Contracts.Connection.ConnectionType.Demo ? OandaConnectionType.FxPractice : OandaConnectionType.FxTrade; var oandaConnection = _oandaApiConnectionFactory.CreateConnection(oandaServer, await _connectionsSecretService.GetConnectionSecret(conn.Id)); var oandaAccount = oandaConnection.GetAccount(conn.ExternalAccountId); var oandaAccountDetails = await oandaAccount.GetDetailsAsync(); conn.Balance = oandaAccountDetails.Balance; conn.ProfitLoss = oandaAccountDetails.Pl; conn.OpenTrades = _mapper.Map <IEnumerable <Contracts.Trade.Trade> >(await oandaAccount.Trades.GetOpenTradesAsync()); } } // Return connections enhanced with open trades return(connections); }
/// <summary> /// Get the candles in monthly packages /// </summary> /// <returns>Candles in a month</returns> private async Task <ICollection <Contracts.Candle> > GetCandlesBetween(Contracts.InstrumentName instrument, Contracts.Granularity granularity, DateTime utcFrom, DateTime utcTo) { // Authenticate to OANDA with the master account var oandaConnection = _oandaApiConnectionFactory.CreateConnection(OandaConnectionType.FxPractice, _configuration["Oanda-MasterToken"]); // Get candles var oandaInstrument = _mapper.Map <InstrumentName>(instrument); var oandaGranularity = _mapper.Map <CandlestickGranularity>(granularity); var candles = await oandaConnection.GetInstrument(oandaInstrument).GetCandlesByTimeAsync(oandaGranularity, utcFrom, utcTo); return(_mapper.Map <ICollection <Contracts.Candle> >(candles)); }
/// <summary> /// Do a tick and handle trading /// </summary> /// <returns>A task</returns> public async Task Tick() { // Collect tradeable instrument granularities var tradeableGranularities = GetInstrumentGranularities().Where(granularity => granularity.IsTradeable); // Collect latest candles for all relevant granularities for the tick time var tickRelevantGranularities = tradeableGranularities.Where(granularity => IsTickRelevant(granularity.Granularity)); var instrumentTicks = new List <InstrumentWithCandles>(); foreach (var granularity in tickRelevantGranularities) { var lastTwoCandles = await GetLastTwoCandles(granularity.Instrument.Name, granularity.Granularity); // Last candle is not complete -> market is open if (!lastTwoCandles.ElementAt(1).Complete) { instrumentTicks.Add(new InstrumentWithCandles() { InstrumentName = granularity.Instrument.Name, Granularity = granularity.Granularity, Candles = new List <Candle>() { _mapper.Map <Candle>(lastTwoCandles.ElementAt(0)) } }); } } if (instrumentTicks.Count() == 0) { // Do not execute engine tick return; } // Save them to the storage account foreach (var tick in instrumentTicks) { // Let's eliminate storage account speed, failures should be handles // within the service anyway so don't care is a safe option here _ = _instrumentStorageService.StoreInstrumentCandles(tick); } // Tick them to the engine var tradeSignals = await TickToEngine(instrumentTicks); // Save trade signals generated var tradeSignalsToDb = _mapper.Map <IEnumerable <Database.Trade.TradeSignal> >(tradeSignals); _dbContext.AddRange(tradeSignalsToDb); _dbContext.SaveChanges(); // Make a trade for each for each connection var connections = GetConnections(); foreach (var conn in connections) { // Oanda if (conn.Broker == DbConnections.Broker.Oanda) { var oandaServer = conn.Type == ContractConnections.ConnectionType.Demo ? OandaConnectionType.FxPractice : OandaConnectionType.FxTrade; var oandaConnection = _oandaApiConnectionFactory.CreateConnection(oandaServer, await _connectionsSecretService.GetConnectionSecret(conn.Id)); foreach (var ts in tradeSignals) { // Use the 40% of liquid cash var account = await oandaConnection.GetAccount(conn.ExternalAccountId).GetDetailsAsync(); var positionSize = (account.Balance + account.UnrealizedPL) * .4; await oandaConnection .GetAccount(conn.ExternalAccountId) .Trades .OpenTradeAsync( _mapper.Map <GeriRemenyi.Oanda.V20.Client.Model.InstrumentName>(ts.Instrument), _mapper.Map <SdkTrade.TradeDirection>(ts.Direction), Convert.ToInt64(Math.Floor(positionSize)), 900 // Stop loss: 900 pips ); } } } }