Gmx V2 Prices (#8)

* Update prices api

* Update worker services in Program.cs
This commit is contained in:
Oda
2025-02-03 16:33:41 +07:00
committed by GitHub
parent 17114ac787
commit ff0433c349
9 changed files with 126 additions and 36 deletions

View File

@@ -22,7 +22,7 @@ public abstract class PricesBaseWorker<T> : BaseWorker<T> where T : class
logger, logger,
delay, delay,
workerService workerService
) )
{ {
_pricesService = pricesService; _pricesService = pricesService;
_statisticService = statisticService; _statisticService = statisticService;
@@ -31,7 +31,7 @@ public abstract class PricesBaseWorker<T> : BaseWorker<T> where T : class
protected override async Task Run(CancellationToken cancellationToken) protected override async Task Run(CancellationToken cancellationToken)
{ {
var tickers = _statisticService.GetTickers(); var tickers = await _statisticService.GetTickers();
foreach (var ticker in tickers) foreach (var ticker in tickers)
{ {

View File

@@ -11,7 +11,7 @@ public interface IStatisticService
SpotlightOverview GetLastSpotlight(DateTime dateTime); SpotlightOverview GetLastSpotlight(DateTime dateTime);
IList<TopVolumeTicker> GetLastTopVolumeTicker(); IList<TopVolumeTicker> GetLastTopVolumeTicker();
Task<List<Trade>> GetLeadboardPositons(); Task<List<Trade>> GetLeadboardPositons();
IList<Enums.Ticker> GetTickers(); Task<IList<Enums.Ticker>> GetTickers();
Task UpdateLeaderboard(); Task UpdateLeaderboard();
Task UpdateNoobiesboard(); Task UpdateNoobiesboard();
Task UpdateSpotlight(); Task UpdateSpotlight();

View File

@@ -35,9 +35,10 @@ public class PricesService : IPricesService
if (account == null) if (account == null)
throw new Exception($"Enable to found account for exchange {exchange}"); throw new Exception($"Enable to found account for exchange {exchange}");
var lastCandles = await _candleRepository.GetCandles(exchange, ticker, timeframe, DateTime.UtcNow.AddDays(-2)); var lastCandles =
await _candleRepository.GetCandles(exchange, ticker, timeframe, DateTime.UtcNow.AddDays(-2));
var lastCandle = lastCandles.LastOrDefault(); var lastCandle = lastCandles.LastOrDefault();
var startDate = lastCandle != null ? lastCandle.Date : CandleExtensions.GetPreloadSinceFromTimeframe(timeframe); var startDate = lastCandle != null ? lastCandle.Date : new DateTime(2017, 1, 1);
var newCandles = await _exchangeService.GetCandles(account, ticker, startDate, timeframe); var newCandles = await _exchangeService.GetCandles(account, ticker, startDate, timeframe);
var candles = !lastCandles.Any() ? newCandles : newCandles.Where(c => c.Date > lastCandle?.Date); var candles = !lastCandles.Any() ? newCandles : newCandles.Where(c => c.Date > lastCandle?.Date);
@@ -54,7 +55,6 @@ public class PricesService : IPricesService
if (candlesInserted > 0) if (candlesInserted > 0)
_logger.LogInformation($"[{exchange}][{ticker}][{timeframe}] New candles inserted : {candlesInserted}"); _logger.LogInformation($"[{exchange}][{ticker}][{timeframe}] New candles inserted : {candlesInserted}");
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -159,9 +159,9 @@ public class StatisticService : IStatisticService
return _statisticRepository.GetTopVolumeTickers(from); return _statisticRepository.GetTopVolumeTickers(from);
} }
public IList<Ticker> GetTickers() public async Task<IList<Ticker>> GetTickers()
{ {
return _evmManager.GetAvailableTicker().Result; return await _evmManager.GetAvailableTicker();
} }
public async Task UpdateSpotlight() public async Task UpdateSpotlight()
@@ -199,7 +199,7 @@ public class StatisticService : IStatisticService
await _statisticRepository.SaveSpotligthtOverview(overview); await _statisticRepository.SaveSpotligthtOverview(overview);
} }
var tickers = GetTickers(); var tickers = await GetTickers();
foreach (var scenario in scenarios) foreach (var scenario in scenarios)
{ {

View File

@@ -11,6 +11,7 @@ using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Abstractions; using Managing.Infrastructure.Evm.Abstractions;
using Managing.Infrastructure.Evm.Models; using Managing.Infrastructure.Evm.Models;
using Managing.Infrastructure.Evm.Models.Gmx.v1; using Managing.Infrastructure.Evm.Models.Gmx.v1;
using Managing.Infrastructure.Evm.Models.Gmx.v2;
using Managing.Infrastructure.Evm.Referentials; using Managing.Infrastructure.Evm.Referentials;
using Managing.Infrastructure.Evm.Services; using Managing.Infrastructure.Evm.Services;
using Managing.Infrastructure.Evm.Services.Gmx; using Managing.Infrastructure.Evm.Services.Gmx;
@@ -38,6 +39,12 @@ public class EvmManager : IEvmManager
private Dictionary<string, Dictionary<string, decimal>> _geckoPrices; private Dictionary<string, Dictionary<string, decimal>> _geckoPrices;
private readonly GmxV2Service _gmxV2Service; private readonly GmxV2Service _gmxV2Service;
private readonly List<Ticker> _eligibleTickers = new List<Ticker>()
{
Ticker.BTC, Ticker.ETH, Ticker.LINK, Ticker.GMX, Ticker.SOL, Ticker.XRP, Ticker.ARB, Ticker.BNB, Ticker.AAVE,
Ticker.PEPE, Ticker.DOGE, Ticker.UNI
};
public EvmManager(IEnumerable<ISubgraphPrices> subgraphs) public EvmManager(IEnumerable<ISubgraphPrices> subgraphs)
{ {
var defaultChain = ChainService.GetEthereum(); var defaultChain = ChainService.GetEthereum();
@@ -366,27 +373,24 @@ public class EvmManager : IEvmManager
Timeframe timeframe) Timeframe timeframe)
{ {
string gmxTimeframe = GmxHelpers.GeTimeframe(timeframe); string gmxTimeframe = GmxHelpers.GeTimeframe(timeframe);
var gmxPrices = await _httpClient.GetFromJsonAsync<GmxPrices>( var gmxPrices = await _httpClient.GetFromJsonAsync<GmxV2Prices>(
$"https://stats.gmx.io/api/candles/{ticker}?preferableChainId=42161&period={gmxTimeframe}&from={startDate.ToUnixTimestamp()}&preferableSource=fast"); $"https://arbitrum-api.gmxinfra.io/prices/candles?tokenSymbol={ticker}&period={gmxTimeframe}&limit=10000");
//var subgraph = _subgraphs.First(s => s.GetProvider() == subgraphProvider);
//var prices = await subgraph.GetPrices(ticker, startDate, timeframe);
//if (prices == null)
//{
// foreach (var subgraphFallback in _subgraphs.Where(s => s.GetProvider() != subgraphProvider))
// {
// prices = await subgraphFallback.GetPrices(ticker, startDate, timeframe);
// if (prices != null)
// break;
// }
//}
if (gmxPrices == null) if (gmxPrices == null)
return null; return null;
gmxPrices.prices.RemoveAt(gmxPrices.prices.Count - 1); gmxPrices.Candles = gmxPrices.Candles.Where(p => p[0] >= startDate.ToUnixTimestamp()).ToList();
return gmxPrices.prices.Select(p => GmxMappers.Map(p, ticker, timeframe)).ToList(); gmxPrices.Candles.RemoveAt(gmxPrices.Candles.Count - 1);
var candles = new List<Candle>();
var timeBetweenCandles = gmxPrices.Candles[0][0] - gmxPrices.Candles[1][0];
for (int i = 0; i < gmxPrices.Candles.Count; i++)
{
var c = GmxV2Mappers.Map(gmxPrices.Candles[i], ticker, timeframe, (int)timeBetweenCandles);
candles.Add(c);
}
return candles.OrderBy(c => c.Date).ToList();
} }
public decimal GetVolume(SubgraphProvider subgraphProvider, Ticker ticker) public decimal GetVolume(SubgraphProvider subgraphProvider, Ticker ticker)
@@ -403,9 +407,13 @@ public class EvmManager : IEvmManager
public async Task<List<Ticker>> GetAvailableTicker() public async Task<List<Ticker>> GetAvailableTicker()
{ {
var subgraph = GetSubgraph(SubgraphProvider.Gbc); var tokenList = await _httpClient.GetFromJsonAsync<GmxV2TokenList>(
var pairs = await subgraph.GetTickers(); "https://arbitrum-api.gmxinfra.io/tokens");
return pairs.ToList();
if (tokenList == null)
return null;
return GmxV2Mappers.Map(tokenList).Where(t => _eligibleTickers.Contains(t)).ToList();
} }
public async Task<Candle> GetCandle(SubgraphProvider subgraphProvider, Ticker ticker) public async Task<Candle> GetCandle(SubgraphProvider subgraphProvider, Ticker ticker)

View File

@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
using Newtonsoft.Json;
namespace Managing.Infrastructure.Evm.Models.Gmx.v2;
public class GmxV2Prices
{
[JsonProperty("period")]
[JsonPropertyName("period")]
public string Period { get; set; }
[JsonProperty("candles")]
[JsonPropertyName("candles")]
public List<List<double>> Candles { get; set; }
}

View File

@@ -0,0 +1,30 @@
using System.Text.Json.Serialization;
using Newtonsoft.Json;
namespace Managing.Infrastructure.Evm.Models.Gmx.v2;
public class GmxV2TokenList
{
[JsonProperty("tokens")]
[JsonPropertyName("tokens")]
public List<Token> Tokens { get; set; }
}
public class Token
{
[JsonProperty("symbol")]
[JsonPropertyName("symbol")]
public string Symbol { get; set; }
[JsonProperty("address")]
[JsonPropertyName("address")]
public string Address { get; set; }
[JsonProperty("decimals")]
[JsonPropertyName("decimals")]
public int Decimals { get; set; }
[JsonProperty("synthetic")]
[JsonPropertyName("synthetic")]
public bool? Synthetic { get; set; }
}

View File

@@ -2,6 +2,7 @@ using System.Numerics;
using Managing.ABI.GmxV2.SyntheticsReader.ContractDefinition; using Managing.ABI.GmxV2.SyntheticsReader.ContractDefinition;
using Managing.Common; using Managing.Common;
using Managing.Core; using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.Trades; using Managing.Domain.Trades;
using Managing.Infrastructure.Evm.Models.Gmx.v2; using Managing.Infrastructure.Evm.Models.Gmx.v2;
using Nethereum.Web3; using Nethereum.Web3;
@@ -104,4 +105,39 @@ internal static class GmxV2Mappers
ShortTokenPrice = mp.ShortTokenPrice ShortTokenPrice = mp.ShortTokenPrice
}).ToList(); }).ToList();
} }
public static Candle Map(List<double> marketPrices, Enums.Ticker ticker, Enums.Timeframe timeframe, int timeBetween)
{
return new Candle()
{
Date = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]).AddSeconds(timeBetween).AddSeconds(-1),
OpenTime = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]),
Open = Convert.ToDecimal(marketPrices[1]),
High = Convert.ToDecimal(marketPrices[2]),
Low = Convert.ToDecimal(marketPrices[3]),
Close = Convert.ToDecimal(marketPrices[4]),
Exchange = Enums.TradingExchanges.Evm,
Ticker = ticker.ToString(),
Timeframe = timeframe
};
}
public static List<Enums.Ticker> Map(GmxV2TokenList tokenList)
{
var tokens = new List<Enums.Ticker>();
foreach (var t in tokenList.Tokens)
{
try
{
var ticker = MiscExtensions.ParseEnum<Enums.Ticker>(t.Symbol);
tokens.Add(ticker);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
return tokens;
}
} }

View File

@@ -157,8 +157,7 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
enabled: !!selectedAccount && !!selectedTimeframe, enabled: !!selectedAccount && !!selectedTimeframe,
queryFn: () => { queryFn: () => {
if (selectedAccount && selectedTimeframe) { if (selectedAccount && selectedTimeframe) {
// return dataClient.data_GetTickers(selectedAccount, selectedTimeframe) return dataClient.data_GetTickers(selectedAccount, selectedTimeframe)
return [Ticker.BTC]
} }
}, },
queryKey: ['tickers', selectedAccount, selectedTimeframe], queryKey: ['tickers', selectedAccount, selectedTimeframe],
@@ -262,25 +261,27 @@ const BacktestModal: React.FC<BacktestModalProps> = ({
</FormInput> </FormInput>
<FormInput label="Days" htmlFor="days"> <FormInput label="Days" htmlFor="days">
<Slider <input
id="days" id="days"
type="number"
value={days} value={days}
onChange={(e: any) => setDays(e.target.value)} onChange={(e: any) => setDays(e.target.value)}
step="1" step="1"
min="-360" min="-360"
max="-1" max="-1"
></Slider> ></input>
</FormInput> </FormInput>
<FormInput label="Balance" htmlFor="balance"> <FormInput label="Balance" htmlFor="balance">
<Slider <input
id="balance" id="balance"
type='number'
value={balance} value={balance}
onChange={(e: any) => setBalance(e.target.value)} onChange={(e: any) => setBalance(e.target.value)}
step="1000" step="1000"
min="1000" min="1000"
max="100000" max="100000"
></Slider> ></input>
</FormInput> </FormInput>
<FormInput label="Scenario" htmlFor="scenarioName"> <FormInput label="Scenario" htmlFor="scenarioName">