docker files fixes from liaqat

This commit is contained in:
alirehmani
2024-05-03 16:39:25 +05:00
commit 464a8730e8
587 changed files with 44288 additions and 0 deletions

View File

@@ -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);
}

View 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,
};
}
}
}

View File

@@ -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"));
}
}
}

View 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);
}
}
}

View 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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View 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
}

View 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();
}
}

View File

@@ -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;
}
}

View 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();
}
}
}

View 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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -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>