Add funding rate watcher (#2)
* Add FundingRate interfaces and worker * Add build on PR * Remove zip * Specify the solution path * Add build for worker too * Set up StatisticService.cs for funding rate * Add Fundingrate alerts * Send alert when big funding rate change + add SlashCommands.cs for fundingrate * Remove fixtures * Refact names * Renames
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using System.Net.Http.Json;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Managing.Infrastructure.Evm.Services;
|
||||
|
||||
@@ -10,14 +12,32 @@ public class TradaoService : ITradaoService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
private readonly HashSet<Enums.Ticker> _deltaNeutralTickers = new()
|
||||
{
|
||||
Enums.Ticker.BTC,
|
||||
Enums.Ticker.ARB,
|
||||
Enums.Ticker.ETH,
|
||||
Enums.Ticker.AVAX,
|
||||
Enums.Ticker.BNB,
|
||||
Enums.Ticker.SOL,
|
||||
Enums.Ticker.LINK,
|
||||
Enums.Ticker.OP,
|
||||
Enums.Ticker.UNI,
|
||||
Enums.Ticker.AAVE,
|
||||
Enums.Ticker.PEPE,
|
||||
Enums.Ticker.WIF,
|
||||
};
|
||||
|
||||
public TradaoService()
|
||||
{
|
||||
_httpClient = new HttpClient(); ;
|
||||
_httpClient = new HttpClient();
|
||||
;
|
||||
}
|
||||
|
||||
public async Task<List<Trader>> GetBadTrader()
|
||||
{
|
||||
var bestTraders = await _httpClient.GetFromJsonAsync<TradaoList>($"https://api.tradao.xyz/v1/td/dashboard/42161/gmx/pnlTop/500/asc/2592000/0/?current=1&limit=500&order=asc&window=2592000&chain=42161&exchange=gmx&openPosition=0");
|
||||
var bestTraders = await _httpClient.GetFromJsonAsync<TradaoList>(
|
||||
$"https://api.tradao.xyz/v1/td/dashboard/42161/gmx/pnlTop/500/asc/2592000/0/?current=1&limit=500&order=asc&window=2592000&chain=42161&exchange=gmx&openPosition=0");
|
||||
|
||||
if (bestTraders == null || bestTraders.row.Count == 0)
|
||||
{
|
||||
@@ -30,7 +50,8 @@ public class TradaoService : ITradaoService
|
||||
|
||||
public async Task<List<Trader>> GetBestTrader()
|
||||
{
|
||||
var bestTraders = await _httpClient.GetFromJsonAsync<TradaoList>($"https://api.tradao.xyz/v1/td/dashboard/42161/gmx/pnlTop/500/desc/2592000/0/?current=1&limit=500&order=desc&window=2592000&chain=42161&exchange=gmx&openPosition=0");
|
||||
var bestTraders = await _httpClient.GetFromJsonAsync<TradaoList>(
|
||||
$"https://api.tradao.xyz/v1/td/dashboard/42161/gmx/pnlTop/500/desc/2592000/0/?current=1&limit=500&order=desc&window=2592000&chain=42161&exchange=gmx&openPosition=0");
|
||||
|
||||
if (bestTraders == null || bestTraders.row.Count == 0)
|
||||
{
|
||||
@@ -42,7 +63,9 @@ public class TradaoService : ITradaoService
|
||||
|
||||
public async Task<List<Trade>> GetTrades(string address)
|
||||
{
|
||||
var response = await _httpClient.GetFromJsonAsync<TradaoUserDetails>($"https://api.tradao.xyz/v1/td/trader/42161/gmx/insights/{address}");
|
||||
var response =
|
||||
await _httpClient.GetFromJsonAsync<TradaoUserDetails>(
|
||||
$"https://api.tradao.xyz/v1/td/trader/42161/gmx/insights/{address}");
|
||||
|
||||
var trades = new List<Trade>();
|
||||
|
||||
@@ -60,7 +83,7 @@ public class TradaoService : ITradaoService
|
||||
Convert.ToDecimal(position.averagePrice),
|
||||
Convert.ToDecimal(position.position) / Convert.ToDecimal(position.collateral),
|
||||
address, position.liqPrice
|
||||
);
|
||||
);
|
||||
|
||||
trades.Add(trade);
|
||||
}
|
||||
@@ -68,12 +91,15 @@ public class TradaoService : ITradaoService
|
||||
return trades;
|
||||
}
|
||||
|
||||
|
||||
private async Task<List<Trader>> GetTraderDetails(TradaoList traders)
|
||||
{
|
||||
var result = new List<Trader>();
|
||||
foreach (var trader in traders.row)
|
||||
{
|
||||
var response = await _httpClient.GetFromJsonAsync<TradaoUserDetails>($"https://api.tradao.xyz/v1/td/trader/42161/gmx/insights/{trader.user}");
|
||||
var response =
|
||||
await _httpClient.GetFromJsonAsync<TradaoUserDetails>(
|
||||
$"https://api.tradao.xyz/v1/td/trader/42161/gmx/insights/{trader.user}");
|
||||
|
||||
if (response != null)
|
||||
result.Add(Map(response, trader.user));
|
||||
@@ -95,4 +121,94 @@ public class TradaoService : ITradaoService
|
||||
Roi = Convert.ToDecimal(response.summary.roi)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<FundingRate>> GetFundingRates()
|
||||
{
|
||||
_httpClient.DefaultRequestHeaders.Accept.Clear();
|
||||
_httpClient.DefaultRequestHeaders.Accept.Add(
|
||||
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
|
||||
|
||||
var response =
|
||||
await _httpClient.GetFromJsonAsync<List<TradaoFundingRate>>("https://api.tradao.xyz/v1/td/fr/all");
|
||||
|
||||
return Map(response);
|
||||
}
|
||||
|
||||
private List<FundingRate> Map(List<TradaoFundingRate>? response)
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
return new List<FundingRate>();
|
||||
}
|
||||
|
||||
var result = new List<FundingRate>();
|
||||
|
||||
foreach (var fundingRate in response)
|
||||
{
|
||||
var ticker = Map(fundingRate.Symbol);
|
||||
|
||||
if (ticker == null || fundingRate.ExchangeName != "gmxv2")
|
||||
continue;
|
||||
|
||||
if (!_deltaNeutralTickers.Contains(ticker.Value))
|
||||
continue;
|
||||
|
||||
var longRate = GetApy(fundingRate.LongFundingRate);
|
||||
var shortRate = GetApy(fundingRate.ShortFundingRate);
|
||||
result.Add(new FundingRate
|
||||
{
|
||||
Ticker = ticker.Value,
|
||||
Rate = longRate,
|
||||
Direction = Enums.TradeDirection.Long,
|
||||
Date = DateTimeOffset.FromUnixTimeSeconds(fundingRate.Timestamp).DateTime
|
||||
});
|
||||
|
||||
result.Add(new FundingRate
|
||||
{
|
||||
Ticker = ticker.Value,
|
||||
Rate = shortRate,
|
||||
Direction = Enums.TradeDirection.Short,
|
||||
Date = DateTimeOffset.FromUnixTimeSeconds(fundingRate.Timestamp).DateTime
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Enums.Ticker? Map(string fundingRateSymbol)
|
||||
{
|
||||
try
|
||||
{
|
||||
return MiscExtensions.ParseEnum<Enums.Ticker>(fundingRateSymbol);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public decimal GetApy(string fundingRate)
|
||||
{
|
||||
try
|
||||
{
|
||||
decimal rate = Convert.ToDecimal(fundingRate, System.Globalization.CultureInfo.InvariantCulture);
|
||||
return rate * 100 * 24 * 365;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// Handle the case where conversion fails due to an incorrect format
|
||||
// Log the error, return 0, or handle as appropriate for your application
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class TradaoFundingRate
|
||||
{
|
||||
public string Symbol { get; set; }
|
||||
public string ChainId { get; set; }
|
||||
public string ExchangeName { get; set; }
|
||||
public string LongFundingRate { get; set; }
|
||||
public string ShortFundingRate { get; set; }
|
||||
public long Timestamp { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user