Postgres (#30)
* Add postgres * Migrate users * Migrate geneticRequest * Try to fix Concurrent call * Fix asyncawait * Fix async and concurrent * Migrate backtests * Add cache for user by address * Fix backtest migration * Fix not open connection * Fix backtest command error * Fix concurrent * Fix all concurrency * Migrate TradingRepo * Fix scenarios * Migrate statistic repo * Save botbackup * Add settings et moneymanagement * Add bot postgres * fix a bit more backups * Fix bot model * Fix loading backup * Remove cache market for read positions * Add workers to postgre * Fix workers api * Reduce get Accounts for workers * Migrate synth to postgre * Fix backtest saved * Remove mongodb * botservice decorrelation * Fix tradingbot scope call * fix tradingbot * fix concurrent * Fix scope for genetics * Fix account over requesting * Fix bundle backtest worker * fix a lot of things * fix tab backtest * Remove optimized moneymanagement * Add light signal to not use User and too much property * Make money management lighter * insert indicators to awaitable * Migrate add strategies to await * Refactor scenario and indicator retrieval to use asynchronous methods throughout the application * add more async await * Add services * Fix and clean * Fix bot a bit * Fix bot and add message for cooldown * Remove fees * Add script to deploy db * Update dfeeploy script * fix script * Add idempotent script and backup * finish script migration * Fix did user and agent name on start bot
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
@@ -9,7 +8,7 @@ namespace Managing.Infrastructure.Exchanges.Abstractions;
|
||||
|
||||
public interface IExchangeProcessor
|
||||
{
|
||||
public Enums.TradingExchanges Exchange();
|
||||
public TradingExchanges Exchange();
|
||||
void LoadClient(Account account);
|
||||
Task<Trade> OpenTrade(
|
||||
Account account,
|
||||
@@ -27,7 +26,7 @@ public interface IExchangeProcessor
|
||||
decimal? takeProfitPrice = null);
|
||||
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<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);
|
||||
|
||||
@@ -1,52 +1,12 @@
|
||||
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
|
||||
@@ -65,18 +25,14 @@ namespace Managing.Infrastructure.Exchanges
|
||||
{
|
||||
Ticker = ticker.ToString(),
|
||||
Timeframe = timeframe,
|
||||
BaseVolume = candle.Volume,
|
||||
Volume = 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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,10 +243,10 @@ namespace Managing.Infrastructure.Exchanges
|
||||
return processor.GetFee(account);
|
||||
}
|
||||
|
||||
public decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
public async Task<decimal> GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
var processor = GetProcessor(account);
|
||||
return processor.GetPrice(account, ticker, date);
|
||||
return await processor.GetPrice(account, ticker, date);
|
||||
}
|
||||
|
||||
public Candle GetCandle(Account account, Ticker ticker, DateTime date)
|
||||
@@ -274,12 +274,12 @@ namespace Managing.Infrastructure.Exchanges
|
||||
return tickers.ToList();
|
||||
}
|
||||
|
||||
public decimal GetBestPrice(Account account, Ticker ticker, decimal lastPrice, decimal quantity,
|
||||
public async Task<decimal> GetBestPrice(Account account, Ticker ticker, decimal lastPrice, decimal quantity,
|
||||
TradeDirection direction)
|
||||
{
|
||||
if (IsEvmExchange(account))
|
||||
{
|
||||
return GetPrice(account, ticker, DateTime.UtcNow);
|
||||
return await GetPrice(account, ticker, DateTime.UtcNow);
|
||||
}
|
||||
|
||||
return GetOrderbook(account, ticker).GetBestPrice(direction, quantity);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
@@ -12,12 +11,12 @@ namespace Managing.Infrastructure.Exchanges.Exchanges
|
||||
{
|
||||
public abstract void LoadClient(Account account);
|
||||
public abstract Task<bool> CancelOrder(Account account, Ticker ticker);
|
||||
public abstract Enums.TradingExchanges Exchange();
|
||||
public abstract 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> 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);
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
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.Statistics;
|
||||
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 Task<List<FundingRate>> GetFundingRates()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<IEnumerable<Position>> GetPositions(Account account)
|
||||
{
|
||||
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,
|
||||
decimal? stopLossPrice = null,
|
||||
decimal? takeProfitPrice = null)
|
||||
{
|
||||
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, "", ticker);
|
||||
|
||||
trade.Price = binanceOrder.Price;
|
||||
trade.SetStatus(binanceOrder.Status);
|
||||
trade.SetExchangeOrderId("");
|
||||
trade.SetMessage("");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -83,9 +83,9 @@ public class EvmProcessor : BaseProcessor
|
||||
return _evmManager.GetFee(Constants.Chains.Arbitrum).Result;
|
||||
}
|
||||
|
||||
public override decimal GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
public override async Task<decimal> GetPrice(Account account, Ticker ticker, DateTime date)
|
||||
{
|
||||
return GetCandle(account, ticker, date).Close;
|
||||
return (await GetCandles(account, ticker, date, Timeframe.OneMinute, true)).Last().Close;
|
||||
}
|
||||
|
||||
public override async Task<decimal> GetQuantityInPosition(Account account, Ticker ticker)
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
using CryptoExchange.Net.Authentication;
|
||||
using FTX.Net.Interfaces.Clients;
|
||||
using FTX.Net.Objects;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Statistics;
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
decimal? stopLossPrice = null,
|
||||
decimal? takeProfitPrice = null)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public override Task<List<FundingRate>> GetFundingRates()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<IEnumerable<Position>> GetPositions(Account account)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
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.Statistics;
|
||||
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 Task<List<FundingRate>> GetFundingRates()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override Task<IEnumerable<Position>> GetPositions(Account account)
|
||||
{
|
||||
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,
|
||||
decimal? stopLossPrice = null,
|
||||
decimal? takeProfitPrice = null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
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;
|
||||
@@ -73,22 +72,18 @@ namespace Managing.Infrastructure.Exchanges.Helpers
|
||||
"", result.Error?.Message);
|
||||
}
|
||||
|
||||
public static Candle Map(IBinanceKline binanceKline, Ticker ticker, Enums.TradingExchanges exchange)
|
||||
public static Candle Map(IBinanceKline binanceKline, Ticker ticker, TradingExchanges exchange)
|
||||
{
|
||||
return new Candle
|
||||
{
|
||||
Date = binanceKline.CloseTime,
|
||||
BaseVolume = binanceKline.Volume,
|
||||
Volume = 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
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
@@ -178,13 +177,13 @@ namespace Managing.Infrastructure.Exchanges.Helpers
|
||||
public static Candle Map(
|
||||
FTXKline ftxKline,
|
||||
Ticker ticker,
|
||||
Enums.TradingExchanges exchange,
|
||||
TradingExchanges exchange,
|
||||
Timeframe timeframe)
|
||||
{
|
||||
return new Candle
|
||||
{
|
||||
Date = ftxKline.OpenTime,
|
||||
BaseVolume = ftxKline.Volume ?? 0,
|
||||
Volume = ftxKline.Volume ?? 0,
|
||||
Close = ftxKline.ClosePrice,
|
||||
High = ftxKline.HighPrice,
|
||||
Low = ftxKline.LowPrice,
|
||||
|
||||
Reference in New Issue
Block a user