docker files fixes from liaqat
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Abstractions;
|
||||
|
||||
public interface IExchangeProcessor
|
||||
{
|
||||
public Enums.TradingExchanges Exchange();
|
||||
void LoadClient(Account account);
|
||||
Task<Trade> OpenTrade(
|
||||
Account account,
|
||||
Ticker ticker,
|
||||
TradeDirection direction,
|
||||
decimal price,
|
||||
decimal quantity,
|
||||
decimal? leverage = null,
|
||||
TradeType tradeType = TradeType.Limit,
|
||||
bool reduceOnly = false,
|
||||
bool isForPaperTrading = false,
|
||||
DateTime? currentDate = null,
|
||||
bool ioc = true);
|
||||
Task<decimal> GetBalance(Account account, bool isForPaperTrading = false);
|
||||
Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false);
|
||||
decimal GetPrice(Account account, Ticker ticker, DateTime date);
|
||||
Task<Trade> GetTrade(Account account, string order, Ticker ticker);
|
||||
Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval);
|
||||
decimal GetVolume(Account account, Ticker ticker);
|
||||
Task<List<Trade>> GetTrades(Account account, Ticker ticker);
|
||||
Task<bool> CancelOrder(Account account, Ticker ticker);
|
||||
decimal GetFee(Account account, bool isForPaperTrading = false);
|
||||
Candle GetCandle(Account account, Ticker ticker, DateTime date);
|
||||
Task<decimal> GetQuantityInPosition(Account account, Ticker ticker);
|
||||
Orderbook GetOrderbook(Account account, Ticker ticker);
|
||||
Task<List<Trade>> GetOrders(Account account, Ticker ticker);
|
||||
Task<Trade> GetTrade(string reference, string orderId, Ticker ticker);
|
||||
}
|
||||
82
src/Managing.Infrastructure.Exchanges/CandleHelpers.cs
Normal file
82
src/Managing.Infrastructure.Exchanges/CandleHelpers.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Binance.Net.Interfaces;
|
||||
using FTX.Net.Objects.Models;
|
||||
using Kraken.Net.Objects.Models;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Infrastructure.Databases.MongoDb.Collections;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges
|
||||
{
|
||||
public static class CandleHelpers
|
||||
{
|
||||
public static CandleDto Convert(IBinanceKline candle, Ticker ticker, Timeframe timeframe)
|
||||
{
|
||||
return new CandleDto()
|
||||
{
|
||||
Ticker = ticker.ToString(),
|
||||
Timeframe = timeframe,
|
||||
BaseVolume = candle.Volume,
|
||||
Close = candle.ClosePrice,
|
||||
CloseTime = candle.CloseTime,
|
||||
Open = candle.OpenPrice,
|
||||
OpenTime = candle.OpenTime,
|
||||
High = candle.HighPrice,
|
||||
Low = candle.LowPrice,
|
||||
QuoteVolume = candle.QuoteVolume,
|
||||
TakerBuyBaseVolume = candle.TakerBuyBaseVolume,
|
||||
TakerBuyQuoteVolume = candle.TakerBuyQuoteVolume,
|
||||
TradeCount = candle.TradeCount,
|
||||
};
|
||||
}
|
||||
|
||||
public static CandleDto Convert(KrakenStreamKline candle, Ticker ticker, Timeframe timeframe)
|
||||
{
|
||||
return new CandleDto()
|
||||
{
|
||||
Ticker = ticker.ToString(),
|
||||
Timeframe = timeframe,
|
||||
BaseVolume = candle.Volume,
|
||||
Close = candle.ClosePrice,
|
||||
CloseTime = candle.CloseTime,
|
||||
Open = candle.OpenPrice,
|
||||
OpenTime = candle.OpenTime,
|
||||
High = candle.HighPrice,
|
||||
Low = candle.LowPrice,
|
||||
QuoteVolume = candle.VolumeWeightedAveragePrice,
|
||||
TradeCount = candle.TradeCount
|
||||
};
|
||||
}
|
||||
|
||||
internal static Candle Map(FTXKline lastCandle)
|
||||
{
|
||||
return new Candle
|
||||
{
|
||||
OpenTime = lastCandle.OpenTime,
|
||||
High = lastCandle.HighPrice,
|
||||
Low = lastCandle.LowPrice,
|
||||
Close = lastCandle.ClosePrice,
|
||||
Open = lastCandle.OpenPrice
|
||||
};
|
||||
}
|
||||
|
||||
internal static Candle Map(IBinanceStreamKline candle, Ticker ticker, Timeframe timeframe)
|
||||
{
|
||||
return new Candle()
|
||||
{
|
||||
Ticker = ticker.ToString(),
|
||||
Timeframe = timeframe,
|
||||
BaseVolume = candle.Volume,
|
||||
Close = candle.ClosePrice,
|
||||
Date = candle.CloseTime,
|
||||
Open = candle.OpenPrice,
|
||||
OpenTime = candle.OpenTime,
|
||||
High = candle.HighPrice,
|
||||
Low = candle.LowPrice,
|
||||
QuoteVolume = candle.QuoteVolume,
|
||||
TakerBuyBaseVolume = candle.TakerBuyBaseVolume,
|
||||
TakerBuyQuoteVolume = candle.TakerBuyQuoteVolume,
|
||||
TradeCount = candle.TradeCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Configurations
|
||||
{
|
||||
public static class ExchangeConfiguration
|
||||
{
|
||||
public static ApiCredentials GetBinanceApiCredentials(this IConfiguration configuration)
|
||||
{
|
||||
return new ApiCredentials(configuration.GetValue<string>("Credentials:Binance:Key"), configuration.GetValue<string>("Credentials:Binance:Secret"));
|
||||
}
|
||||
|
||||
public static ApiCredentials GetKrakenApiCredentials(this IConfiguration configuration)
|
||||
{
|
||||
return new ApiCredentials(configuration.GetValue<string>("Credentials:Kraken:Key"), configuration.GetValue<string>("Credentials:Kraken:Secret"));
|
||||
}
|
||||
|
||||
public static ApiCredentials GetFtxApiCredentials(this IConfiguration configuration)
|
||||
{
|
||||
return new ApiCredentials(configuration.GetValue<string>("Credentials:Ftx:Key"), configuration.GetValue<string>("Credentials:Ftx:Secret"));
|
||||
}
|
||||
}
|
||||
}
|
||||
242
src/Managing.Infrastructure.Exchanges/ExchangeService.cs
Normal file
242
src/Managing.Infrastructure.Exchanges/ExchangeService.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Candles;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Infrastructure.Exchanges.Abstractions;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges
|
||||
{
|
||||
public class ExchangeService : IExchangeService
|
||||
{
|
||||
private readonly ILogger<ExchangeService> _logger;
|
||||
private readonly ICandleRepository _candleRepository;
|
||||
private readonly IEnumerable<IExchangeProcessor> _exchangeProcessor;
|
||||
|
||||
public ExchangeService(ILogger<ExchangeService> logger, ICandleRepository candleRepository, IEnumerable<IExchangeProcessor> processor)
|
||||
{
|
||||
_logger = logger;
|
||||
_candleRepository = candleRepository;
|
||||
_exchangeProcessor = processor;
|
||||
}
|
||||
|
||||
#region Trades
|
||||
public async Task<Trade> OpenTrade(
|
||||
Account account,
|
||||
Ticker ticker,
|
||||
TradeDirection direction,
|
||||
decimal price,
|
||||
decimal quantity,
|
||||
decimal? leverage = null,
|
||||
TradeType tradeType = TradeType.Limit,
|
||||
bool reduceOnly = false,
|
||||
bool isForPaperTrading = false,
|
||||
DateTime? currentDate = null,
|
||||
bool ioc = true)
|
||||
{
|
||||
_logger.LogInformation($"OpenMarketTrade - {ticker} - Type: {tradeType} - {direction} - Price: {price} - Quantity: {quantity} - Leverage: {leverage}");
|
||||
|
||||
if (isForPaperTrading)
|
||||
{
|
||||
return BuildEmptyTrade(ticker, price, quantity, direction, leverage, tradeType, currentDate.Value, reduceOnly ? TradeStatus.PendingOpen : TradeStatus.Filled);
|
||||
}
|
||||
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.OpenTrade(account, ticker, direction, price, quantity, leverage, tradeType, reduceOnly, isForPaperTrading, currentDate, ioc);
|
||||
}
|
||||
|
||||
private IExchangeProcessor GetProcessor(Account account)
|
||||
{
|
||||
return _exchangeProcessor.First(e => e.Exchange() == account.Exchange);
|
||||
}
|
||||
|
||||
public Trade BuildEmptyTrade(Ticker ticker, decimal price, decimal quantity, TradeDirection direction, decimal? leverage, TradeType tradeType,
|
||||
DateTime dateTime, TradeStatus tradeStatus)
|
||||
{
|
||||
return new Trade(dateTime, direction, tradeStatus, tradeType, ticker, quantity, price, leverage,
|
||||
Guid.NewGuid().ToString(), "EmptyTrade");
|
||||
}
|
||||
|
||||
public async Task<Trade> OpenStopLoss(Account account, Ticker ticker, TradeDirection originalDirection, decimal stopLossPrice,
|
||||
decimal quantity, bool isForPaperTrading = false, DateTime? currentDate = null)
|
||||
{
|
||||
return await OpenTrade(
|
||||
account,
|
||||
ticker,
|
||||
originalDirection == TradeDirection.Long ? TradeDirection.Short : TradeDirection.Long,
|
||||
stopLossPrice,
|
||||
quantity,
|
||||
tradeType: TradeType.StopLoss,
|
||||
isForPaperTrading: isForPaperTrading,
|
||||
currentDate: currentDate,
|
||||
reduceOnly: true);
|
||||
}
|
||||
|
||||
public async Task<Trade> OpenTakeProfit(Account account, Ticker ticker, TradeDirection originalDirection, decimal takeProfitPrice,
|
||||
decimal quantity, bool isForPaperTrading = false, DateTime? currentDate = null)
|
||||
{
|
||||
return await OpenTrade(
|
||||
account,
|
||||
ticker,
|
||||
originalDirection == TradeDirection.Long ? TradeDirection.Short : TradeDirection.Long,
|
||||
takeProfitPrice,
|
||||
quantity,
|
||||
tradeType: TradeType.TakeProfit,
|
||||
isForPaperTrading: isForPaperTrading,
|
||||
currentDate: currentDate,
|
||||
reduceOnly: true);
|
||||
}
|
||||
|
||||
public Task<Trade> ClosePosition(Account account, Position position, decimal lastPrice, bool isForPaperTrading = false)
|
||||
{
|
||||
var direction = position.OriginDirection == TradeDirection.Long ? TradeDirection.Short : TradeDirection.Long;
|
||||
|
||||
if (isForPaperTrading)
|
||||
{
|
||||
var fake = BuildEmptyTrade(position.Open.Ticker,
|
||||
lastPrice,
|
||||
position.Open.Quantity,
|
||||
direction,
|
||||
position.Open.Leverage,
|
||||
TradeType.Market,
|
||||
position.Open.Date,
|
||||
TradeStatus.Filled);
|
||||
return Task.FromResult(fake);
|
||||
}
|
||||
|
||||
var processor = GetProcessor(account);
|
||||
var closedTrade = processor.OpenTrade(
|
||||
account,
|
||||
position.Ticker,
|
||||
direction,
|
||||
lastPrice,
|
||||
position.Open.Quantity,
|
||||
position.Open.Leverage,
|
||||
tradeType: TradeType.Market,
|
||||
reduceOnly: true).Result;
|
||||
|
||||
if (account.Exchange != Common.Enums.TradingExchanges.Evm)
|
||||
{
|
||||
closedTrade.Price = processor.GetTrade(account, closedTrade.ExchangeOrderId, closedTrade.Ticker).Result.Price;
|
||||
}
|
||||
|
||||
return Task.FromResult(closedTrade);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
public async Task<bool> CancelOrder(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.CancelOrder(account, ticker);
|
||||
}
|
||||
|
||||
public async Task<Trade> GetTrade(Account account, string orderId, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetTrade(account, orderId, ticker);
|
||||
}
|
||||
|
||||
public async Task<Trade> GetTrade(string reference, string orderId, Ticker ticker)
|
||||
{
|
||||
var processor = _exchangeProcessor.First(e => e.Exchange() == Common.Enums.TradingExchanges.Evm);
|
||||
return await processor.GetTrade(reference, orderId, ticker);
|
||||
}
|
||||
|
||||
public async Task<List<Trade>> GetTrades(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetTrades(account, ticker);
|
||||
|
||||
}
|
||||
|
||||
public async Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe timeframe)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetCandles(account, ticker, startDate, timeframe);
|
||||
}
|
||||
|
||||
public async Task<List<Candle>> GetCandlesInflux(TradingExchanges exchange, Ticker ticker, DateTime startDate, Timeframe timeframe)
|
||||
{
|
||||
var candlesFromRepo = await _candleRepository.GetCandles(exchange, ticker, timeframe, startDate);
|
||||
return candlesFromRepo.ToList();
|
||||
}
|
||||
|
||||
public async Task<decimal> GetBalance(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
if (isForPaperTrading)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetBalance(account);
|
||||
}
|
||||
|
||||
public decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetFee(account);
|
||||
}
|
||||
|
||||
public decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetPrice(account, ticker, date);
|
||||
}
|
||||
|
||||
public Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetCandle(account, ticker, date);
|
||||
}
|
||||
|
||||
public async Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetQuantityInPosition(account, ticker);
|
||||
}
|
||||
|
||||
public decimal GetVolume(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetVolume(account, ticker);
|
||||
}
|
||||
|
||||
public async Task<List<Ticker>> GetTickers(Account account, Timeframe timeframe)
|
||||
{
|
||||
var tickers = await _candleRepository.GetTickersAsync(account.Exchange, timeframe, DateTime.UtcNow.AddDays(-2));
|
||||
return tickers.ToList();
|
||||
}
|
||||
|
||||
public decimal GetBestPrice(Account account, Ticker ticker, decimal lastPrice, decimal quantity, TradeDirection direction)
|
||||
{
|
||||
if (account.Exchange == Common.Enums.TradingExchanges.Evm)
|
||||
{
|
||||
return GetPrice(account, ticker, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
return GetOrderbook(account, ticker).GetBestPrice(direction, quantity);
|
||||
}
|
||||
|
||||
public Orderbook GetOrderbook(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetOrderbook(account, ticker);
|
||||
}
|
||||
|
||||
public async Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetBalances(account, isForPaperTrading);
|
||||
}
|
||||
|
||||
public async Task<List<Trade>> GetOpenOrders(Account account, Ticker ticker)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return await processor.GetOrders(account, ticker);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
src/Managing.Infrastructure.Exchanges/ExchangeStream.cs
Normal file
41
src/Managing.Infrastructure.Exchanges/ExchangeStream.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Binance.Net.Interfaces.Clients;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Shared;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Infrastructure.Exchanges.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges;
|
||||
|
||||
public class ExchangeStream : IExchangeStream
|
||||
{
|
||||
private readonly ILogger<StreamService> logger;
|
||||
private readonly IBinanceSocketClient _binanceSocketClient;
|
||||
|
||||
public ExchangeStream(IBinanceSocketClient binanceSocketClient, ILogger<StreamService> logger)
|
||||
{
|
||||
_binanceSocketClient = binanceSocketClient;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public async Task StartBinanceWorker(Ticker ticker, Func<Candle, Task> action)
|
||||
{
|
||||
logger.LogInformation($"Starting binance worker for {ticker}");
|
||||
|
||||
await _binanceSocketClient.SpotApi.ExchangeData.SubscribeToKlineUpdatesAsync(BinanceHelpers.ToBinanceTicker(ticker), Binance.Net.Enums.KlineInterval.OneSecond, candle =>
|
||||
{
|
||||
if (candle.Data.Data?.Final == true)
|
||||
{
|
||||
//action((candle) => { CandleHelpers.Map(candle.Data.Data, ticker, Timeframe.FiveMinutes)});
|
||||
action(CandleHelpers.Map(candle.Data.Data, ticker, Timeframe.FiveMinutes));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async Task StopBinanceWorker()
|
||||
{
|
||||
logger.LogInformation($"Stoping all Binance worker subscription");
|
||||
await _binanceSocketClient.UnsubscribeAllAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Exchanges.Abstractions;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Exchanges
|
||||
{
|
||||
public abstract class BaseProcessor : IExchangeProcessor
|
||||
{
|
||||
public abstract void LoadClient(Account account);
|
||||
public abstract Task<bool> CancelOrder(Account account, Ticker ticker);
|
||||
public abstract Enums.TradingExchanges Exchange();
|
||||
public abstract Task<decimal> GetBalance(Account account, bool isForPaperTrading = false);
|
||||
public abstract Candle GetCandle(Account account, Ticker ticker, DateTime date);
|
||||
public abstract Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval);
|
||||
public abstract decimal GetFee(Account account, bool isForPaperTrading = false);
|
||||
public abstract decimal GetPrice(Account account, Ticker ticker, DateTime date);
|
||||
public abstract Task<decimal> GetQuantityInPosition(Account account, Ticker ticker);
|
||||
public abstract Task<Trade> GetTrade(Account account, string order, Ticker ticker);
|
||||
public abstract Task<List<Trade>> GetTrades(Account account, Ticker ticker);
|
||||
public abstract decimal GetVolume(Account account, Ticker ticker);
|
||||
public abstract Task<Trade> OpenTrade(Account account, Ticker ticker, TradeDirection direction, decimal price, decimal quantity, decimal? leverage = null, Enums.TradeType tradeType = Enums.TradeType.Limit, bool reduceOnly = false, bool isForPaperTrading = false, DateTime? currentDate = null, bool ioc = true);
|
||||
public abstract Orderbook GetOrderbook(Account account, Ticker ticker);
|
||||
public abstract Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false);
|
||||
public abstract Task<List<Trade>> GetOrders(Account account, Ticker ticker);
|
||||
public abstract Task<Trade> GetTrade(string reference, string orderId, Ticker ticker);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
using Binance.Net.Clients;
|
||||
using Binance.Net.Enums;
|
||||
using Binance.Net.Interfaces.Clients;
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Exchanges.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Exchanges;
|
||||
|
||||
public class BinanceProcessor : BaseProcessor
|
||||
{
|
||||
private ILogger<BinanceProcessor> _logger;
|
||||
private IBinanceRestClient _binanceClient;
|
||||
|
||||
public BinanceProcessor(ILogger<BinanceProcessor> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override async Task<bool> CancelOrder(Account account, Ticker ticker)
|
||||
{
|
||||
var binanceResult = await _binanceClient.UsdFuturesApi.Trading.CancelAllOrdersAsync(BinanceHelpers.ToBinanceTicker(ticker));
|
||||
return binanceResult.Success;
|
||||
}
|
||||
|
||||
public override Enums.TradingExchanges Exchange() => Enums.TradingExchanges.Binance;
|
||||
|
||||
public override async Task<decimal> GetBalance(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
var balance = 0m;
|
||||
var binanceBalance = await _binanceClient.UsdFuturesApi.Account.GetBalancesAsync();
|
||||
foreach (var item in binanceBalance.Data)
|
||||
{
|
||||
balance += item.AvailableBalance;
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
|
||||
public override Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe timeframe)
|
||||
{
|
||||
var binanceCandles = await _binanceClient.UsdFuturesApi.ExchangeData.GetKlinesAsync(BinanceHelpers.ToBinanceTicker(ticker),
|
||||
BinanceHelpers.Map(timeframe), startDate);
|
||||
|
||||
return (List<Candle>)binanceCandles.Data.Select(binanceKline => BinanceHelpers.Map(binanceKline, ticker, account.Exchange));
|
||||
}
|
||||
|
||||
public override decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Orderbook GetOrderbook(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<List<Trade>> GetOrders(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
var binancePrice = _binanceClient.UsdFuturesApi.ExchangeData.GetPriceAsync(BinanceHelpers.ToBinanceTicker(ticker)).Result.Data;
|
||||
return binancePrice.Price;
|
||||
}
|
||||
|
||||
public override async Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<Trade> GetTrade(Account account, string order, Ticker ticker)
|
||||
{
|
||||
var binanceOrder = await _binanceClient.UsdFuturesApi.Trading.GetOrderAsync(BinanceHelpers.ToBinanceTicker(ticker), origClientOrderId: order);
|
||||
return BinanceHelpers.Map(binanceOrder.Data);
|
||||
}
|
||||
|
||||
public override Task<Trade> GetTrade(string reference, string orderId, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<List<Trade>> GetTrades(Account account, Ticker ticker)
|
||||
{
|
||||
var binanceOrder =
|
||||
await _binanceClient.UsdFuturesApi.Trading.GetOrdersAsync(BinanceHelpers.ToBinanceTicker(ticker));
|
||||
return (List<Trade>)binanceOrder.Data.Select(o => BinanceHelpers.Map(o));
|
||||
}
|
||||
|
||||
public override decimal GetVolume(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void LoadClient(Account account)
|
||||
{
|
||||
var credentials = new ApiCredentials(account.Key, account.Secret);
|
||||
_binanceClient = new BinanceRestClient((options) => { options.ApiCredentials = credentials; });
|
||||
}
|
||||
|
||||
public override async Task<Trade> OpenTrade(Account account, Ticker ticker, TradeDirection direction, decimal price, decimal quantity, decimal? leverage = null, TradeType tradeType = TradeType.Limit, bool reduceOnly = false, bool isForPaperTrading = false, DateTime? currentDate = null, bool ioc = true)
|
||||
{
|
||||
var trade = new Trade(DateTime.Now, direction, TradeStatus.PendingOpen, tradeType, ticker, quantity, price, leverage, "", "");
|
||||
trade.SetQuantity(quantity, GetQuantityPrecision(account, ticker));
|
||||
trade.SetPrice(price, GetPricePrecision(account, ticker));
|
||||
|
||||
if (trade.Quantity <= 0)
|
||||
throw new InvalidOperationException(
|
||||
$"Minimum quantity not match, cannot execute trade {direction} for {ticker}.");
|
||||
|
||||
var binanceOrderType = BinanceHelpers.BinanceOrderTypeMap(tradeType);
|
||||
var binanceResult = await _binanceClient.UsdFuturesApi.Trading.PlaceOrderAsync(
|
||||
BinanceHelpers.ToBinanceTicker(ticker),
|
||||
direction != TradeDirection.Long ? OrderSide.Sell : OrderSide.Buy,
|
||||
binanceOrderType,
|
||||
price: binanceOrderType == FuturesOrderType.Limit ? trade.Price : null,
|
||||
quantity: trade.Quantity,
|
||||
reduceOnly: reduceOnly,
|
||||
priceProtect: true,
|
||||
timeInForce: binanceOrderType == FuturesOrderType.Limit ? TimeInForce.GoodTillCanceled : null,
|
||||
activationPrice: binanceOrderType == FuturesOrderType.Limit ? trade.Price : null,
|
||||
stopPrice: binanceOrderType == FuturesOrderType.StopMarket ? trade.Price : null);
|
||||
|
||||
_logger.LogInformation("Exchange result : {0}", JsonConvert.SerializeObject(binanceResult));
|
||||
|
||||
var binanceOrderExecuted = BinanceHelpers.Map(binanceResult, leverage);
|
||||
|
||||
if (binanceResult.Success)
|
||||
{
|
||||
var binanceOrder = await GetTrade(account, binanceOrderExecuted.ExchangeOrderId, ticker);
|
||||
|
||||
trade.Price = binanceOrder.Price;
|
||||
trade.SetStatus(binanceOrder.Status);
|
||||
trade.SetExchangeOrderId(binanceOrderExecuted.ExchangeOrderId);
|
||||
trade.SetMessage(binanceOrderExecuted.Message);
|
||||
}
|
||||
return trade;
|
||||
}
|
||||
|
||||
private int GetPricePrecision(Account account, Ticker ticker)
|
||||
{
|
||||
var binanceFutureInfo = _binanceClient.UsdFuturesApi.ExchangeData.GetExchangeInfoAsync().Result.Data;
|
||||
var precision = binanceFutureInfo.Symbols.Single(p => p.Name == BinanceHelpers.ToBinanceTicker(ticker))
|
||||
.PriceFilter.TickSize;
|
||||
return MathHelpers.GetDecimalPlaces(precision);
|
||||
}
|
||||
|
||||
private int GetQuantityPrecision(Account account, Ticker ticker)
|
||||
{
|
||||
var binanceFutureInfo = _binanceClient.UsdFuturesApi.ExchangeData.GetExchangeInfoAsync().Result.Data;
|
||||
var precision = binanceFutureInfo.Symbols.Single(p => p.Name == BinanceHelpers.ToBinanceTicker(ticker)).QuantityPrecision;
|
||||
return Convert.ToInt32(precision);
|
||||
}
|
||||
}
|
||||
172
src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs
Normal file
172
src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using Managing.Application.Abstractions.Repositories;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Evm;
|
||||
using Managing.Domain.Trades;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Exchanges;
|
||||
|
||||
public class EvmProcessor : BaseProcessor
|
||||
{
|
||||
public override Enums.TradingExchanges Exchange() => Enums.TradingExchanges.Evm;
|
||||
|
||||
private ILogger<EvmProcessor> _logger;
|
||||
private IEvmManager _evmManager;
|
||||
|
||||
public EvmProcessor(ILogger<EvmProcessor> logger, IEvmManager evmManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_evmManager = evmManager;
|
||||
}
|
||||
|
||||
public override async Task<bool> CancelOrder(Account account, Ticker ticker)
|
||||
{
|
||||
return await _evmManager.CancelOrders(account, ticker);
|
||||
}
|
||||
|
||||
|
||||
public override async Task<decimal> GetBalance(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
//var balances = await _evmManager.GetAllBalancesOnAllChain(account.Key);
|
||||
//var balanceAmount = 0m;
|
||||
|
||||
//foreach (var balance in balances)
|
||||
//{
|
||||
// balanceAmount += balance.Value;
|
||||
//}
|
||||
|
||||
var evmBalance = await _evmManager.GetTokenBalance(Constants.Chains.Arbitrum, Ticker.USDC, account.Key);
|
||||
return evmBalance.Balance;
|
||||
}
|
||||
|
||||
public override async Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
var balances = await _evmManager.GetAllBalancesOnAllChain(account.Key);
|
||||
return Map(balances);
|
||||
}
|
||||
|
||||
private List<Balance> Map(List<EvmBalance> balances)
|
||||
{
|
||||
return balances.ConvertAll(balance => new Balance
|
||||
{
|
||||
TokenName = balance.TokenName,
|
||||
Price = balance.Price,
|
||||
Value = balance.Value,
|
||||
Amount = balance.Balance,
|
||||
TokenAdress = balance.TokenAddress,
|
||||
Chain = balance.Chain
|
||||
});
|
||||
}
|
||||
|
||||
public override Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
return _evmManager.GetCandle(SubgraphProvider.Gbc, ticker).Result;
|
||||
}
|
||||
|
||||
public override async Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval)
|
||||
{
|
||||
return await _evmManager.GetCandles(SubgraphProvider.Gbc, ticker, startDate, interval);
|
||||
}
|
||||
|
||||
public override decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
return _evmManager.GetFee(Constants.Chains.Arbitrum).Result;
|
||||
}
|
||||
|
||||
public override decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
return GetCandle(account, ticker, date).Close;
|
||||
}
|
||||
|
||||
public override async Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
{
|
||||
return await _evmManager.QuantityInPosition(Constants.Chains.Arbitrum, account.Key, ticker);
|
||||
}
|
||||
|
||||
public override async Task<Trade> GetTrade(Account account, string order, Ticker ticker)
|
||||
{
|
||||
return await _evmManager.GetTrade(account, Constants.Chains.Arbitrum, ticker);
|
||||
}
|
||||
|
||||
public override async Task<Trade> GetTrade(string reference, string orderId, Ticker ticker)
|
||||
{
|
||||
return await _evmManager.GetTrade(reference, Constants.Chains.Arbitrum, ticker);
|
||||
}
|
||||
|
||||
public override decimal GetVolume(Account account, Ticker ticker)
|
||||
{
|
||||
var volume = _evmManager.GetVolume(SubgraphProvider.ChainlinkPrice, ticker);
|
||||
return volume;
|
||||
}
|
||||
|
||||
public override async Task<Trade> OpenTrade(
|
||||
Account account,
|
||||
Ticker ticker,
|
||||
TradeDirection direction,
|
||||
decimal price,
|
||||
decimal quantity,
|
||||
decimal? leverage = null,
|
||||
TradeType tradeType = TradeType.Limit,
|
||||
bool reduceOnly = false,
|
||||
bool isForPaperTrading = false,
|
||||
DateTime? currentDate = null,
|
||||
bool ioc = true)
|
||||
{
|
||||
Trade trade;
|
||||
if (reduceOnly)
|
||||
{
|
||||
if (tradeType is TradeType.TakeProfit
|
||||
or TradeType.StopLoss)
|
||||
{
|
||||
// If trade type is TP or SL we create DecreaseOrder
|
||||
trade = await _evmManager.DecreaseOrder(account, tradeType, ticker, direction, price, quantity, leverage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Trade requested is not an SL nor TP
|
||||
// Price is the current price
|
||||
// We create Decrease position
|
||||
trade = await _evmManager.DecreasePosition(account, ticker, direction, price, quantity, leverage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
trade = await _evmManager.IncreasePosition(account, ticker, direction, price, quantity, leverage);
|
||||
}
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
public override async Task<List<Trade>> GetOrders(Account account, Ticker ticker)
|
||||
{
|
||||
return await _evmManager.GetOrders(account, ticker);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region Not implemented
|
||||
|
||||
public override void LoadClient(Account account)
|
||||
{
|
||||
// No client needed
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<List<Trade>> GetTrades(Account account, Ticker ticker)
|
||||
{
|
||||
// Use by commandHandler to get trades list
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Orderbook GetOrderbook(Account account, Ticker ticker)
|
||||
{
|
||||
// Not use because EVM do not based on an orderbook
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
199
src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs
Normal file
199
src/Managing.Infrastructure.Exchanges/Exchanges/FtxProcessor.cs
Normal file
@@ -0,0 +1,199 @@
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using FTX.Net.Clients;
|
||||
using FTX.Net.Interfaces.Clients;
|
||||
using FTX.Net.Objects;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Exchanges.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Exchanges;
|
||||
|
||||
public class FtxProcessor : BaseProcessor
|
||||
{
|
||||
private IFTXClient _ftxClient;
|
||||
private ILogger<FtxProcessor> _logger;
|
||||
|
||||
public FtxProcessor(ILogger<FtxProcessor> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override Enums.TradingExchanges Exchange() => Enums.TradingExchanges.Ftx;
|
||||
|
||||
public override void LoadClient(Account account)
|
||||
{
|
||||
var credentials = new ApiCredentials(account.Key, account.Secret);
|
||||
|
||||
var ftxConfig = new FTXClientOptions()
|
||||
{
|
||||
SubaccountName = account.Name
|
||||
};
|
||||
_ftxClient = new FTXClient(ftxConfig);
|
||||
}
|
||||
|
||||
|
||||
public override async Task<bool> CancelOrder(Account account, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxResult = await _ftxClient.TradeApi.Trading.CancelAllOrdersAsync(FtxHelpers.ToFtxTicker(ticker));
|
||||
return ftxResult.Success;
|
||||
}
|
||||
|
||||
public override async Task<decimal> GetBalance(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
LoadClient(account);
|
||||
|
||||
var balance = 0m;
|
||||
var ftxBalance = await _ftxClient.TradeApi.Account.GetBalancesAsync();
|
||||
foreach (var item in ftxBalance.Data)
|
||||
{
|
||||
balance += item.UsdValue;
|
||||
}
|
||||
return balance;
|
||||
}
|
||||
|
||||
public override Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
LoadClient(account);
|
||||
|
||||
var ftxKlines = _ftxClient.TradeApi.ExchangeData.GetKlinesAsync(FtxHelpers.ToFtxTicker(ticker),
|
||||
FTX.Net.Enums.KlineInterval.OneMinute, date.AddHours(-2.5)).Result.Data;
|
||||
if (ftxKlines != null && ftxKlines.Any())
|
||||
{
|
||||
var lastCandle = ftxKlines.ToList().LastOrDefault();
|
||||
return CandleHelpers.Map(lastCandle);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe timeframe)
|
||||
{
|
||||
LoadClient(account);
|
||||
|
||||
var candles = new List<Candle>();
|
||||
var ftxCandles = await _ftxClient.TradeApi.ExchangeData.GetKlinesAsync(FtxHelpers.ToFtxTicker(ticker),
|
||||
FtxHelpers.Map(timeframe), startDate);
|
||||
|
||||
if (ftxCandles.Success)
|
||||
candles.AddRange(ftxCandles.Data.SkipLast(1).Select(ftxKline => FtxHelpers.Map(ftxKline, ticker, account.Exchange, timeframe)));
|
||||
|
||||
return candles;
|
||||
}
|
||||
|
||||
public override decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxResult = _ftxClient.TradeApi.Account.GetAccountInfoAsync().Result.Data;
|
||||
return ftxResult.TakerFee;
|
||||
}
|
||||
|
||||
public override decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxKlines = _ftxClient.TradeApi.ExchangeData.GetKlinesAsync(FtxHelpers.ToFtxTicker(ticker),
|
||||
FTX.Net.Enums.KlineInterval.OneMinute, date.AddHours(-2.5)).Result.Data;
|
||||
if (ftxKlines != null && ftxKlines.Any())
|
||||
{
|
||||
return ftxKlines.ToList().LastOrDefault().ClosePrice;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override async Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
{
|
||||
var ftxTickerBalance = _ftxClient.TradeApi.Account.GetPositionsAsync().Result.Data;
|
||||
return ftxTickerBalance.FirstOrDefault(f => f.Future == FtxHelpers.ToFtxTicker(ticker)).Quantity;
|
||||
}
|
||||
|
||||
public override async Task<Trade> GetTrade(Account account, string order, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxOrder = await _ftxClient.TradeApi.Trading.GetOrderByClientOrderIdAsync(order);
|
||||
return FtxHelpers.Map(ftxOrder.Data);
|
||||
}
|
||||
|
||||
public override async Task<List<Trade>> GetTrades(Account account, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxOrder = await _ftxClient.TradeApi.Trading.GetOrdersAsync(ticker.ToString());
|
||||
return (List<Trade>)ftxOrder.Data.Select(o => FtxHelpers.Map(o));
|
||||
}
|
||||
|
||||
public override decimal GetVolume(Account account, Ticker ticker)
|
||||
{
|
||||
var futureStats = _ftxClient.TradeApi.ExchangeData.GetFutureStatsAsync(FtxHelpers.ToFtxTicker(ticker)).Result.Data;
|
||||
return futureStats.Volume;
|
||||
}
|
||||
|
||||
public override async Task<Trade> OpenTrade(Account account, Ticker ticker, TradeDirection direction, decimal price, decimal quantity, decimal? leverage = null, TradeType tradeType = TradeType.Limit, bool reduceOnly = false, bool isForPaperTrading = false, DateTime? currentDate = null, bool ioc = true)
|
||||
{
|
||||
LoadClient(account);
|
||||
|
||||
var trade = new Trade(DateTime.Now, direction, TradeStatus.PendingOpen, tradeType, ticker, quantity, price, leverage, "", "");
|
||||
|
||||
trade.SetQuantity(quantity, 6);
|
||||
|
||||
Trade ftxOrder;
|
||||
if (tradeType == TradeType.StopLoss || tradeType == TradeType.TakeProfitLimit || tradeType == TradeType.StopMarket)
|
||||
{
|
||||
var ftxTriggerOrderType = FtxHelpers.FtxTriggerOrderTypeMap(tradeType);
|
||||
var ftxResult = await _ftxClient.TradeApi.Trading.PlaceTriggerOrderAsync(FtxHelpers.ToFtxTicker(ticker),
|
||||
direction != TradeDirection.Long ? FTX.Net.Enums.OrderSide.Sell : FTX.Net.Enums.OrderSide.Buy,
|
||||
ftxTriggerOrderType,
|
||||
triggerPrice: price,
|
||||
reduceOnly: true,
|
||||
retryUntilFilled: false,
|
||||
quantity: quantity);
|
||||
_logger.LogInformation("Exchange result : {0}", JsonConvert.SerializeObject(ftxResult));
|
||||
ftxOrder = FtxHelpers.Map(ftxResult, leverage);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ftxOrderType = FtxHelpers.FtxOrderTypeMap(tradeType);
|
||||
var ftxResult = await _ftxClient.TradeApi.Trading.PlaceOrderAsync(FtxHelpers.ToFtxTicker(ticker),
|
||||
direction != TradeDirection.Long ? FTX.Net.Enums.OrderSide.Sell : FTX.Net.Enums.OrderSide.Buy,
|
||||
ftxOrderType,
|
||||
price: ftxOrderType == FTX.Net.Enums.OrderType.Limit ? price : null,
|
||||
quantity: quantity,
|
||||
clientOrderId: Guid.NewGuid().ToString(),
|
||||
immediateOrCancel: ioc);
|
||||
_logger.LogInformation("Exchange result : {0}", JsonConvert.SerializeObject(ftxResult));
|
||||
ftxOrder = FtxHelpers.Map(ftxResult, leverage);
|
||||
}
|
||||
|
||||
trade.SetStatus(ftxOrder.Status);
|
||||
trade.SetExchangeOrderId(ftxOrder.ExchangeOrderId);
|
||||
trade.SetMessage(ftxOrder.Message);
|
||||
trade.Price = ftxOrder.Price;
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
public override Orderbook GetOrderbook(Account account, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var ftxOrderBook = _ftxClient.TradeApi.ExchangeData.GetOrderBookAsync(FtxHelpers.ToFtxTicker(ticker), 100).Result;
|
||||
return FtxHelpers.Map(ftxOrderBook);
|
||||
}
|
||||
|
||||
public override Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<List<Trade>> GetOrders(Account acount, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<Trade> GetTrade(string reference, string orderId, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using Kraken.Net.Clients;
|
||||
using Kraken.Net.Interfaces.Clients;
|
||||
using Kraken.Net.Objects.Options;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Exchanges.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Exchanges;
|
||||
|
||||
public class KrakenProcessor : BaseProcessor
|
||||
{
|
||||
private ILogger<KrakenProcessor> _logger;
|
||||
private IKrakenRestClient _krakenClient;
|
||||
|
||||
public KrakenProcessor(ILogger<KrakenProcessor> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
public override Task<bool> CancelOrder(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Enums.TradingExchanges Exchange() => Enums.TradingExchanges.Kraken;
|
||||
|
||||
public override async Task<decimal> GetBalance(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
LoadClient(account);
|
||||
var balance = await _krakenClient.SpotApi.Account.GetBalancesAsync();
|
||||
balance.Data.TryGetValue("USDT", out decimal krakenBalance);
|
||||
return krakenBalance;
|
||||
}
|
||||
|
||||
public override Task<List<Balance>> GetBalances(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<List<Candle>> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override decimal GetFee(Account account, bool isForPaperTrading = false)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Orderbook GetOrderbook(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<List<Trade>> GetOrders(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
LoadClient(account);
|
||||
var krakenKline = _krakenClient.SpotApi.ExchangeData.GetKlinesAsync(ticker.ToString(),
|
||||
Kraken.Net.Enums.KlineInterval.OneMinute, date).Result.Data.Data.ToList()[0];
|
||||
return (krakenKline.HighPrice + krakenKline.ClosePrice) / 2;
|
||||
}
|
||||
|
||||
public override Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<Trade> GetTrade(Account account, string order, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var krakenOrder = await _krakenClient.SpotApi.Trading.GetOrderAsync(order);
|
||||
return KrakenHelpers.Map(krakenOrder.Data.Values.First());
|
||||
}
|
||||
|
||||
public override Task<Trade> GetTrade(string reference, string orderId, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override async Task<List<Trade>> GetTrades(Account account, Ticker ticker)
|
||||
{
|
||||
LoadClient(account);
|
||||
var krakenOrder = await _krakenClient.SpotApi.Trading.GetOrdersAsync();
|
||||
return (List<Trade>)krakenOrder.Data.Select(o => KrakenHelpers.Map(o));
|
||||
}
|
||||
|
||||
public override decimal GetVolume(Account account, Ticker ticker)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void LoadClient(Account account)
|
||||
{
|
||||
var credentials = new ApiCredentials(account.Key, account.Secret);
|
||||
var krakenConfig = new KrakenRestOptions()
|
||||
{
|
||||
ApiCredentials = credentials
|
||||
};
|
||||
_krakenClient = new KrakenRestClient((options) => { options.ApiCredentials = krakenConfig.ApiCredentials; });
|
||||
}
|
||||
|
||||
public override async Task<Trade> OpenTrade(Account account, Ticker ticker, TradeDirection direction, decimal price, decimal quantity, decimal? leverage = null, TradeType tradeType = TradeType.Limit, bool reduceOnly = false, bool isForPaperTrading = false, DateTime? currentDate = null, bool ioc = true)
|
||||
{
|
||||
LoadClient(account);
|
||||
var trade = new Trade(DateTime.Now, direction, TradeStatus.PendingOpen, tradeType, ticker, quantity, price, leverage, "", "");
|
||||
trade.SetQuantity(quantity, 6);
|
||||
trade.SetPrice(price, 1);
|
||||
|
||||
var order = await _krakenClient.SpotApi.Trading.PlaceOrderAsync(ticker.ToString(),
|
||||
direction != TradeDirection.Long ? Kraken.Net.Enums.OrderSide.Sell : Kraken.Net.Enums.OrderSide.Buy,
|
||||
KrakenHelpers.KrakenOrderTypeMap(tradeType),
|
||||
price: price,
|
||||
quantity: quantity,
|
||||
leverage: leverage);
|
||||
|
||||
_logger.LogInformation("Exchange result : {0}", JsonConvert.SerializeObject(order));
|
||||
var krakenOrderExecuted = GetTrade(account, ((string[])order.Data.OrderIds)[0], ticker).Result;
|
||||
trade.SetStatus(krakenOrderExecuted.Status);
|
||||
trade.SetExchangeOrderId(krakenOrderExecuted.ExchangeOrderId);
|
||||
trade.SetMessage(krakenOrderExecuted.Message);
|
||||
return trade;
|
||||
}
|
||||
}
|
||||
195
src/Managing.Infrastructure.Exchanges/Helpers/BinanceHelpers.cs
Normal file
195
src/Managing.Infrastructure.Exchanges/Helpers/BinanceHelpers.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using Binance.Net.Enums;
|
||||
using Binance.Net.Interfaces;
|
||||
using Binance.Net.Objects.Models.Futures;
|
||||
using CryptoExchange.Net.Objects;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Helpers
|
||||
{
|
||||
public static class BinanceHelpers
|
||||
{
|
||||
public static Trade Map(BinanceFuturesOrder data)
|
||||
{
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
return new Trade(data.CreateTime,
|
||||
(data.Side == OrderSide.Buy) ? TradeDirection.Long : TradeDirection.Short,
|
||||
(TradeStatus)data.Status, (TradeType)data.OriginalType, MiscExtensions.ParseEnum<Ticker>(data.Symbol), data.Quantity, data.AvgPrice, 1,
|
||||
data.ClientOrderId, "");
|
||||
}
|
||||
|
||||
public static FuturesOrderType BinanceOrderTypeMap(TradeType tradeType)
|
||||
{
|
||||
switch (tradeType)
|
||||
{
|
||||
case TradeType.Limit:
|
||||
return FuturesOrderType.Limit;
|
||||
case TradeType.Market:
|
||||
return FuturesOrderType.Market;
|
||||
case TradeType.StopMarket:
|
||||
return FuturesOrderType.StopMarket;
|
||||
case TradeType.StopLossLimit:
|
||||
return FuturesOrderType.Stop;
|
||||
default:
|
||||
return FuturesOrderType.Limit;
|
||||
}
|
||||
}
|
||||
|
||||
public static TradeType BinanceOrderTradeType(FuturesOrderType orderType)
|
||||
{
|
||||
switch (orderType)
|
||||
{
|
||||
case FuturesOrderType.Stop:
|
||||
case FuturesOrderType.Limit:
|
||||
return TradeType.Limit;
|
||||
case FuturesOrderType.Market:
|
||||
return TradeType.Market;
|
||||
case FuturesOrderType.StopMarket:
|
||||
return TradeType.StopMarket;
|
||||
default:
|
||||
return TradeType.Limit;
|
||||
}
|
||||
}
|
||||
|
||||
public static Trade Map(WebCallResult<BinanceFuturesPlacedOrder> result, decimal? leverage = null)
|
||||
{
|
||||
var data = result.Data;
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
return new Trade(DateTime.Now, TradeDirection.None,
|
||||
TradeStatus.Cancelled, TradeType.Market, Ticker.BTC, 0, 0, 0,
|
||||
"", result.Error?.Message);
|
||||
}
|
||||
|
||||
return new Trade(data.UpdateTime,
|
||||
(data.PositionSide == PositionSide.Long) ? TradeDirection.Long : TradeDirection.Short,
|
||||
(TradeStatus)data.Status, (TradeType)data.OriginalType, MiscExtensions.ParseEnum<Ticker>(data.Symbol), data.Quantity, data.Price, leverage,
|
||||
data.ClientOrderId, "");
|
||||
}
|
||||
|
||||
public static Candle Map(IBinanceKline binanceKline, Ticker ticker, Enums.TradingExchanges exchange)
|
||||
{
|
||||
return new Candle
|
||||
{
|
||||
Date = binanceKline.CloseTime,
|
||||
BaseVolume = binanceKline.Volume,
|
||||
Close = binanceKline.ClosePrice,
|
||||
High = binanceKline.HighPrice,
|
||||
Low = binanceKline.LowPrice,
|
||||
Open = binanceKline.OpenPrice,
|
||||
Ticker = ticker.ToString(),
|
||||
QuoteVolume = binanceKline.QuoteVolume,
|
||||
TradeCount = binanceKline.TradeCount,
|
||||
OpenTime = binanceKline.OpenTime,
|
||||
TakerBuyBaseVolume = binanceKline.TakerBuyBaseVolume,
|
||||
TakerBuyQuoteVolume = binanceKline.TakerBuyQuoteVolume,
|
||||
Exchange = exchange
|
||||
};
|
||||
}
|
||||
|
||||
internal static KlineInterval Map(Timeframe interval) => interval switch
|
||||
{
|
||||
Timeframe.FiveMinutes => KlineInterval.FiveMinutes,
|
||||
Timeframe.FifteenMinutes => KlineInterval.FifteenMinutes,
|
||||
Timeframe.ThirtyMinutes => KlineInterval.ThirtyMinutes,
|
||||
Timeframe.OneHour => KlineInterval.OneHour,
|
||||
Timeframe.FourHour => KlineInterval.FourHour,
|
||||
Timeframe.OneDay => KlineInterval.OneDay,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
public static string ToBinanceTicker(Ticker ticker)
|
||||
{
|
||||
switch (ticker)
|
||||
{
|
||||
case Ticker.ADA:
|
||||
return "ADAUSDT";
|
||||
case Ticker.ALGO:
|
||||
return "ALGOUSDT";
|
||||
case Ticker.ATOM:
|
||||
return "ATOMUSDT";
|
||||
case Ticker.AVAX:
|
||||
return "AVAXUSDT";
|
||||
case Ticker.BAT:
|
||||
return "BATUSDT";
|
||||
case Ticker.BNB:
|
||||
return "BNBUSDT";
|
||||
case Ticker.BTC:
|
||||
return "BTCUSDT";
|
||||
case Ticker.CRV:
|
||||
return "CRVUSDT";
|
||||
case Ticker.DEFI:
|
||||
return "DEFIUSDT";
|
||||
case Ticker.DOGE:
|
||||
return "DOGEUSDT";
|
||||
case Ticker.DOT:
|
||||
return "DOTUSDT";
|
||||
case Ticker.DYDX:
|
||||
return "DYDXUSDT";
|
||||
case Ticker.ETC:
|
||||
return "ETCUSDT";
|
||||
case Ticker.ETH:
|
||||
return "ETHUSDT";
|
||||
case Ticker.FTM:
|
||||
return "FTMUSDT";
|
||||
case Ticker.GALA:
|
||||
return "GALAUSDT";
|
||||
case Ticker.GRT:
|
||||
return "GRTUSDT";
|
||||
case Ticker.IMX:
|
||||
return "IMXUSDT";
|
||||
case Ticker.KAVA:
|
||||
return "KAVAUSDT";
|
||||
case Ticker.KSM:
|
||||
return "KSMUSDT";
|
||||
case Ticker.LINK:
|
||||
return "LINKUSDT";
|
||||
case Ticker.LRC:
|
||||
return "LRCUSDT";
|
||||
case Ticker.LTC:
|
||||
return "LTCUSDT";
|
||||
case Ticker.MATIC:
|
||||
return "MATICUSDT";
|
||||
case Ticker.MKR:
|
||||
return "MKRUSDT";
|
||||
case Ticker.NEAR:
|
||||
return "NEARUSDT";
|
||||
case Ticker.NEO:
|
||||
return "NEOUSDT";
|
||||
case Ticker.ONT:
|
||||
return "ONTUSDT";
|
||||
case Ticker.SAND:
|
||||
return "SANDUSDT";
|
||||
case Ticker.SOL:
|
||||
return "SOLUSDT";
|
||||
case Ticker.SRM:
|
||||
return "SRMUSDT";
|
||||
case Ticker.SUSHI:
|
||||
return "SUSHIUSDT";
|
||||
case Ticker.THETA:
|
||||
return "THETAUSDT";
|
||||
case Ticker.UNI:
|
||||
return "UNIUSDT";
|
||||
case Ticker.WAVES:
|
||||
return "WAVESUSDT";
|
||||
case Ticker.XMR:
|
||||
return "XMRUSDT";
|
||||
case Ticker.XRP:
|
||||
return "XRPUSDT";
|
||||
case Ticker.XTZ:
|
||||
return "XTZUSDT";
|
||||
case Ticker.ZEC:
|
||||
return "ZECUSDT";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
286
src/Managing.Infrastructure.Exchanges/Helpers/FtxHelpers.cs
Normal file
286
src/Managing.Infrastructure.Exchanges/Helpers/FtxHelpers.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
using CryptoExchange.Net.Objects;
|
||||
using FTX.Net.Enums;
|
||||
using FTX.Net.Objects.Models;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Helpers
|
||||
{
|
||||
public static class FtxHelpers
|
||||
{
|
||||
public static string ToFtxTicker(Ticker ticker)
|
||||
{
|
||||
switch (ticker)
|
||||
{
|
||||
case Ticker.ADA:
|
||||
return "ADA-PERP";
|
||||
case Ticker.APE:
|
||||
return "APE-PERP";
|
||||
case Ticker.ALICE:
|
||||
return "ALICE-PERP";
|
||||
case Ticker.ALGO:
|
||||
return "ALGO-PERP";
|
||||
case Ticker.ATOM:
|
||||
return "ATOM-PERP";
|
||||
case Ticker.AVAX:
|
||||
return "AVAX-PERP";
|
||||
case Ticker.AXS:
|
||||
return "AXS-PERP";
|
||||
case Ticker.BAT:
|
||||
return "BAT-PERP";
|
||||
case Ticker.BNB:
|
||||
return "BNB-PERP";
|
||||
case Ticker.BTC:
|
||||
return "BTC-PERP";
|
||||
case Ticker.BAL:
|
||||
return "BAL-PERP";
|
||||
case Ticker.C98:
|
||||
return "C98-PERP";
|
||||
case Ticker.CHR:
|
||||
return "CHR-PERP";
|
||||
case Ticker.CHZ:
|
||||
return "CHZ-PERP";
|
||||
case Ticker.COMP:
|
||||
return "COMP-PERP";
|
||||
case Ticker.CRO:
|
||||
return "CRO-PERP";
|
||||
case Ticker.CRV:
|
||||
return "CRV-PERP";
|
||||
case Ticker.CVC:
|
||||
return "CVC-PERP";
|
||||
case Ticker.DEFI:
|
||||
return "DEFI-PERP";
|
||||
case Ticker.DOGE:
|
||||
return "DOGE-PERP";
|
||||
case Ticker.DOT:
|
||||
return "DOT-PERP";
|
||||
case Ticker.DYDX:
|
||||
return "DYDX-PERP";
|
||||
case Ticker.ENS:
|
||||
return "ENS-PERP";
|
||||
case Ticker.ETC:
|
||||
return "ETC-PERP";
|
||||
case Ticker.ETH:
|
||||
return "ETH-PERP";
|
||||
case Ticker.FIL:
|
||||
return "FIL-PERP";
|
||||
case Ticker.FLM:
|
||||
return "FLM-PERP";
|
||||
case Ticker.FTM:
|
||||
return "FTM-PERP";
|
||||
case Ticker.GALA:
|
||||
return "GALA-PERP";
|
||||
case Ticker.GMT:
|
||||
return "GMT-PERP";
|
||||
case Ticker.GRT:
|
||||
return "GRT-PERP";
|
||||
case Ticker.HNT:
|
||||
return "HNT-PERP";
|
||||
case Ticker.IMX:
|
||||
return "IMX-PERP";
|
||||
case Ticker.JASMY:
|
||||
return "JASMY-PERP";
|
||||
case Ticker.KAVA:
|
||||
return "KAVA-PERP";
|
||||
case Ticker.KSM:
|
||||
return "KSM-PERP";
|
||||
case Ticker.LDO:
|
||||
return "LDO-PERP";
|
||||
case Ticker.LINK:
|
||||
return "LINK-PERP";
|
||||
case Ticker.LOOKS:
|
||||
return "LOOKS-PERP";
|
||||
case Ticker.LRC:
|
||||
return "LRC-PERP";
|
||||
case Ticker.LTC:
|
||||
return "LTC-PERP";
|
||||
case Ticker.MANA:
|
||||
return "MANA-PERP";
|
||||
case Ticker.MATIC:
|
||||
return "MATIC-PERP";
|
||||
case Ticker.MKR:
|
||||
return "MKR-PERP";
|
||||
case Ticker.NEAR:
|
||||
return "NEAR-PERP";
|
||||
case Ticker.NEO:
|
||||
return "NEO-PERP";
|
||||
case Ticker.OMG:
|
||||
return "OMG-PERP";
|
||||
case Ticker.ONE:
|
||||
return "ONE-PERP";
|
||||
case Ticker.ONT:
|
||||
return "ONT-PERP";
|
||||
case Ticker.QTUM:
|
||||
return "QTUM-PERP";
|
||||
case Ticker.REEF:
|
||||
return "REEF-PERP";
|
||||
case Ticker.REN:
|
||||
return "REN-PERP";
|
||||
case Ticker.ROSE:
|
||||
return "ROSE-PERP";
|
||||
case Ticker.RSR:
|
||||
return "RSR-PERP";
|
||||
case Ticker.RUNE:
|
||||
return "RUNE-PERP";
|
||||
case Ticker.SAND:
|
||||
return "SAND-PERP";
|
||||
case Ticker.SOL:
|
||||
return "SOL-PERP";
|
||||
case Ticker.SRM:
|
||||
return "SRM-PERP";
|
||||
case Ticker.STMX:
|
||||
return "STMX-PERP";
|
||||
case Ticker.SUSHI:
|
||||
return "SUSHI-PERP";
|
||||
case Ticker.SXP:
|
||||
return "SXP-PERP";
|
||||
case Ticker.THETA:
|
||||
return "THETA-PERP";
|
||||
case Ticker.UNI:
|
||||
return "UNI-PERP";
|
||||
case Ticker.VET:
|
||||
return "VET-PERP";
|
||||
case Ticker.WAVES:
|
||||
return "WAVES-PERP";
|
||||
case Ticker.XMR:
|
||||
return "XMR-PERP";
|
||||
case Ticker.XRP:
|
||||
return "XRP-PERP";
|
||||
case Ticker.XTZ:
|
||||
return "XTZ-PERP";
|
||||
case Ticker.YFI:
|
||||
return "YFI-PERP";
|
||||
case Ticker.ZEC:
|
||||
return "ZEC-PERP";
|
||||
case Ticker.ZIL:
|
||||
return "ZIL-PERP";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public static Trade Map(WebCallResult<FTXOrder> result, decimal? leverage = null)
|
||||
{
|
||||
var data = result.Data;
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
return new Trade(DateTime.Now, TradeDirection.None,
|
||||
TradeStatus.Cancelled, TradeType.Market, Ticker.BTC, 0, 0, 0,
|
||||
"", result.Error?.Message);
|
||||
}
|
||||
|
||||
return new Trade(data.CreateTime,
|
||||
(data.Side == OrderSide.Buy) ? TradeDirection.Long : TradeDirection.Short,
|
||||
(TradeStatus)data.Status, (TradeType)data.Type, MiscExtensions.ParseEnum<Ticker>(data.Symbol), data.Quantity, data.AverageFillPrice ?? 0, leverage,
|
||||
data.ClientOrderId, "");
|
||||
}
|
||||
|
||||
internal static Trade Map(WebCallResult<FTXTriggerOrder> ftxResult, decimal? leverage)
|
||||
{
|
||||
var data = ftxResult.Data;
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
return new Trade(DateTime.Now, TradeDirection.None,
|
||||
TradeStatus.Cancelled, TradeType.Market, Ticker.BTC, 0, 0, 0,
|
||||
"", ftxResult.Error?.Message);
|
||||
}
|
||||
|
||||
return new Trade(data.CreateTime,
|
||||
(data.Side == OrderSide.Buy) ? TradeDirection.Long : TradeDirection.Short,
|
||||
(TradeStatus)data.Status, (TradeType)data.Type, MiscExtensions.ParseEnum<Ticker>(data.Symbol), data.Quantity, data.TriggerPrice ?? 0, leverage,
|
||||
Guid.NewGuid().ToString(), "");
|
||||
}
|
||||
|
||||
public static OrderType FtxOrderTypeMap(TradeType tradeType)
|
||||
{
|
||||
switch (tradeType)
|
||||
{
|
||||
case TradeType.Limit:
|
||||
return OrderType.Limit;
|
||||
case TradeType.Market:
|
||||
return OrderType.Market;
|
||||
default:
|
||||
return OrderType.Limit;
|
||||
}
|
||||
}
|
||||
|
||||
public static Trade Map(FTXOrder data)
|
||||
{
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
return new Trade(data.CreateTime, TradeDirection.None,
|
||||
(TradeStatus)data.Status, (TradeType)data.Type, MiscExtensions.ParseEnum<Ticker>(data.Symbol), data.Quantity, data.AverageFillPrice ?? 0, 0,
|
||||
data.ClientOrderId, "");
|
||||
}
|
||||
|
||||
public static Candle Map(
|
||||
FTXKline ftxKline,
|
||||
Ticker ticker,
|
||||
Enums.TradingExchanges exchange,
|
||||
Timeframe timeframe)
|
||||
{
|
||||
return new Candle
|
||||
{
|
||||
Date = ftxKline.OpenTime,
|
||||
BaseVolume = ftxKline.Volume ?? 0,
|
||||
Close = ftxKline.ClosePrice,
|
||||
High = ftxKline.HighPrice,
|
||||
Low = ftxKline.LowPrice,
|
||||
Open = ftxKline.OpenPrice,
|
||||
Ticker = ticker.ToString(),
|
||||
OpenTime = ftxKline.OpenTime,
|
||||
Exchange = exchange,
|
||||
Timeframe = timeframe
|
||||
};
|
||||
}
|
||||
|
||||
internal static KlineInterval Map(Timeframe interval) => interval switch
|
||||
{
|
||||
Timeframe.FiveMinutes => KlineInterval.FiveMinutes,
|
||||
Timeframe.FifteenMinutes => KlineInterval.FifteenMinutes,
|
||||
Timeframe.OneHour => KlineInterval.OneHour,
|
||||
Timeframe.FourHour => KlineInterval.FourHours,
|
||||
Timeframe.OneDay => KlineInterval.OneDay,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
internal static TriggerOrderType FtxTriggerOrderTypeMap(TradeType tradeType) => tradeType switch
|
||||
{
|
||||
TradeType.StopMarket => TriggerOrderType.Stop,
|
||||
TradeType.StopLimit => TriggerOrderType.Stop,
|
||||
TradeType.StopLoss => TriggerOrderType.Stop,
|
||||
TradeType.TakeProfit => TriggerOrderType.TakeProfit,
|
||||
TradeType.StopLossProfit => TriggerOrderType.Stop,
|
||||
TradeType.StopLossProfitLimit => TriggerOrderType.Stop,
|
||||
TradeType.StopLossLimit => TriggerOrderType.Stop,
|
||||
TradeType.TakeProfitLimit => TriggerOrderType.TakeProfit,
|
||||
TradeType.TrailingStop => TriggerOrderType.TrailingStop,
|
||||
TradeType.TrailingStopLimit => TriggerOrderType.TrailingStop,
|
||||
TradeType.StopLossAndLimit => TriggerOrderType.Stop,
|
||||
TradeType.SettlePosition => TriggerOrderType.Stop,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
internal static Orderbook Map(WebCallResult<FTXOrderbook> ftxOrderBook)
|
||||
{
|
||||
return new Orderbook()
|
||||
{
|
||||
Asks = Map(ftxOrderBook.Data.Asks),
|
||||
Bids = Map(ftxOrderBook.Data.Bids)
|
||||
};
|
||||
}
|
||||
|
||||
private static List<OrderBookEntry> Map(IEnumerable<FTXOrderBookEntry> entry)
|
||||
{
|
||||
return entry.Select(ask => new OrderBookEntry() { Price = ask.Price, Quantity = ask.Quantity}).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using Kraken.Net.Objects.Models;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Trades;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Exchanges.Helpers;
|
||||
|
||||
public static class KrakenHelpers
|
||||
{
|
||||
public static Trade Map(KrakenOrder order)
|
||||
{
|
||||
var leverageParse = order.OrderDetails.Leverage.Split((char)':')[0];
|
||||
long.TryParse(leverageParse, out long leverage);
|
||||
|
||||
return new Trade(order.CreateTime,
|
||||
TradeDirection.None,
|
||||
(TradeStatus)order.Status,
|
||||
(TradeType)order.OrderDetails.Type,
|
||||
MiscExtensions.ParseEnum<Ticker>(order.OrderDetails.Symbol),
|
||||
order.Quantity,
|
||||
order.AveragePrice,
|
||||
leverage,
|
||||
order.ClientOrderId,
|
||||
"");
|
||||
}
|
||||
|
||||
public static Kraken.Net.Enums.OrderType KrakenOrderTypeMap(TradeType tradeType)
|
||||
{
|
||||
switch (tradeType)
|
||||
{
|
||||
case TradeType.Limit:
|
||||
return Kraken.Net.Enums.OrderType.Limit;
|
||||
case TradeType.Market:
|
||||
return Kraken.Net.Enums.OrderType.Market;
|
||||
case TradeType.StopMarket:
|
||||
return Kraken.Net.Enums.OrderType.StopMarket;
|
||||
default:
|
||||
return Kraken.Net.Enums.OrderType.Limit;
|
||||
}
|
||||
}
|
||||
|
||||
internal static Trade Map(KeyValuePair<string, KrakenOrder> o)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Platforms>AnyCPU;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Binance.Net" Version="9.0.5" />
|
||||
<PackageReference Include="CryptoExchange.Net" Version="6.0.3" />
|
||||
<PackageReference Include="FTX.Net" Version="1.0.16" />
|
||||
<PackageReference Include="KrakenExchange.Net" Version="4.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Managing.Application\Managing.Application.csproj" />
|
||||
<ProjectReference Include="..\Managing.Core\Managing.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user