Gmx v2 - Funding rates (#6)
* Setup GMX v2 * Add get markets * Map token with service * Add get market info data * Add get markets * Add get market token prices * Get markets infos multicall * Try call datastore * Add some tests to figure out why datastore call dont work * Update funding rates * clean
This commit is contained in:
531
src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs
Normal file
531
src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Service.cs
Normal file
@@ -0,0 +1,531 @@
|
||||
using System.Numerics;
|
||||
using Managing.ABI.GmxV2.DataStore;
|
||||
using Managing.ABI.GmxV2.DataStore.ContractDefinition;
|
||||
using Managing.ABI.GmxV2.Multicall3.ContractDefinition;
|
||||
using Managing.ABI.GmxV2.Reader;
|
||||
using Managing.ABI.GmxV2.Reader.ContractDefinition;
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Infrastructure.Evm.Models.Gmx.v2;
|
||||
using Managing.Infrastructure.Evm.Referentials;
|
||||
using Managing.Infrastructure.Evm.Services.Gmx;
|
||||
using Nethereum.Contracts;
|
||||
using Nethereum.Contracts.Standards.ERC20.ContractDefinition;
|
||||
using Nethereum.Hex.HexConvertors.Extensions;
|
||||
using Nethereum.Web3;
|
||||
|
||||
public class GmxV2Service
|
||||
{
|
||||
private readonly GmxV2Helpers _helpers = new GmxV2Helpers();
|
||||
|
||||
public GmxV2Service()
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<object> GetMarkets(Web3 web3)
|
||||
{
|
||||
var reader = new ReaderService(web3, Arbitrum.AddressV2.Reader);
|
||||
var result = await reader.GetMarketsQueryAsync(Arbitrum.AddressV2.DataStore, 0, 100);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<GmxMarket>> GetMarketsAsync(Web3 web3)
|
||||
{
|
||||
var getMarketCallData = new GetMarketsFunction
|
||||
{
|
||||
DataStore = Arbitrum.AddressV2.DataStore,
|
||||
Start = 0,
|
||||
End = 100
|
||||
}.GetCallData();
|
||||
|
||||
var call1 = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.Reader,
|
||||
CallData = getMarketCallData
|
||||
};
|
||||
|
||||
var aggregateFunction = new AggregateFunction();
|
||||
aggregateFunction.Calls = new List<Call>();
|
||||
aggregateFunction.Calls.Add(call1);
|
||||
|
||||
var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();
|
||||
var returnCalls = await queryHandler
|
||||
.QueryDeserializingToObjectAsync<AggregateOutputDTO>(aggregateFunction, Arbitrum.AddressV2.Multicall)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var markets = new GetMarketsOutputDTO().DecodeOutput(returnCalls.ReturnData[0].ToHex());
|
||||
var result = new List<GmxMarket>();
|
||||
foreach (var market in markets.ReturnValue1)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.Add(GmxMappers.MapInfos(market));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<GmxMarketInfo> GetMarketInfo(Web3 web3)
|
||||
{
|
||||
var reader = new ReaderService(web3, Arbitrum.AddressV2.Reader);
|
||||
var market = (await GetMarketsAsync(web3)).First();
|
||||
var tokensData = await GetTokensData(web3);
|
||||
var marketPrices = GmxHelpers.GetContractMarketPrices(tokensData, market);
|
||||
var response =
|
||||
await reader.GetMarketInfoQueryAsync(Arbitrum.AddressV2.DataStore, marketPrices, market.MarketToken);
|
||||
|
||||
// Get hashed key to call datastore
|
||||
var marketKeys = GmxKeysService.GetMarketKeys(market.MarketToken);
|
||||
var longInterestUsingLongTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.LongInterestUsingLongToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var longInterestUsingLongTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = longInterestUsingLongTokenCallData
|
||||
};
|
||||
var longInterestUsingShortTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.LongInterestUsingShortToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var longInterestUsingShortTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = longInterestUsingShortTokenCallData
|
||||
};
|
||||
var shortInterestUsingLongTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.ShortInterestUsingLongToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var shortInterestUsingLongTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = shortInterestUsingLongTokenCallData
|
||||
};
|
||||
var shortInterestUsingShortTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.ShortInterestUsingShortToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var shortInterestUsingShortTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = shortInterestUsingShortTokenCallData
|
||||
};
|
||||
|
||||
var dataStoreMulticall = new AggregateFunction();
|
||||
dataStoreMulticall.Calls = new List<Call>();
|
||||
dataStoreMulticall.Calls.Add(longInterestUsingLongTokenCall);
|
||||
dataStoreMulticall.Calls.Add(longInterestUsingShortTokenCall);
|
||||
dataStoreMulticall.Calls.Add(shortInterestUsingLongTokenCall);
|
||||
dataStoreMulticall.Calls.Add(shortInterestUsingShortTokenCall);
|
||||
var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();
|
||||
var returnCalls = await queryHandler
|
||||
.QueryDeserializingToObjectAsync<AggregateOutputDTO>(dataStoreMulticall, Arbitrum.AddressV2.Multicall)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var marketInfos = GmxMappers.Map(response.ReturnValue1);
|
||||
var result = new GmxMarketInfo()
|
||||
{
|
||||
Market = marketInfos,
|
||||
Infos = DecodeFundingRateOutput(returnCalls, marketInfos.IsSameCollaterals)
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<GmxMarketTokenPrice> GetMarketTokenPrice(Web3 web3, bool maximize = true)
|
||||
{
|
||||
var reader = new ReaderService(web3, Arbitrum.AddressV2.Reader);
|
||||
var market = (await GetMarketsAsync(web3)).First();
|
||||
var tokensData = await GetTokensData(web3);
|
||||
var marketPrices = GmxHelpers.GetContractMarketPrices(tokensData, market);
|
||||
var marketProps = new MarketsProps()
|
||||
{
|
||||
MarketToken = market.MarketToken,
|
||||
IndexToken = market.IndexToken,
|
||||
LongToken = market.LongToken,
|
||||
ShortToken = market.ShortToken
|
||||
};
|
||||
|
||||
var response = await reader.GetMarketTokenPriceQueryAsync(Arbitrum.AddressV2.DataStore, marketProps,
|
||||
marketPrices.IndexTokenPrice, marketPrices.LongTokenPrice, marketPrices.ShortTokenPrice,
|
||||
_helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS), maximize);
|
||||
|
||||
return GmxMappers.Map(response);
|
||||
}
|
||||
|
||||
public async Task<bool> GetIsMarketDisabled(Web3 web3)
|
||||
{
|
||||
var dataStoreService = new DataStoreService(web3, Arbitrum.AddressV2.DataStore);
|
||||
var market = (await GetMarketsAsync(web3)).First();
|
||||
var hashString = _helpers.HashString(Constants.GMX.MARKET_DISABLED_KEY);
|
||||
var response = await dataStoreService.GetBoolQueryAsync(_helpers.HashData(
|
||||
new[] { "bytes32", "address" },
|
||||
new object[] { hashString, market.MarketToken }));
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<BigInteger> GetLongInterestAmount(Web3 web3)
|
||||
{
|
||||
var dataStoreService = new DataStoreService(web3, Arbitrum.AddressV2.DataStore);
|
||||
var market = (await GetMarketsAsync(web3)).First();
|
||||
var keys = GmxKeysService.GetMarketKeys(market.MarketToken);
|
||||
var response = await dataStoreService.GetUintQueryAsync(keys.LongInterestUsingLongToken.HexToByteArray());
|
||||
return response;
|
||||
}
|
||||
|
||||
public async Task<List<GmxMarketInfo>> GetMarketInfosAsync(Web3 web3)
|
||||
{
|
||||
var markets = await GetMarketsAsync(web3);
|
||||
var readerResult = new List<GmxMarketInfo>();
|
||||
foreach (var market in markets)
|
||||
{
|
||||
var tokensData = await GetTokensData(web3);
|
||||
var marketPrices = GmxHelpers.GetContractMarketPrices(tokensData, market);
|
||||
var marketProps = new MarketsProps()
|
||||
{
|
||||
MarketToken = market.MarketToken,
|
||||
IndexToken = market.IndexToken,
|
||||
LongToken = market.LongToken,
|
||||
ShortToken = market.ShortToken
|
||||
};
|
||||
var getMarketInfoCallData = new GetMarketInfoFunction
|
||||
{
|
||||
DataStore = Arbitrum.AddressV2.DataStore,
|
||||
Prices = marketPrices,
|
||||
MarketKey = market.MarketToken
|
||||
}.GetCallData();
|
||||
var getMarketInfoCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.Reader,
|
||||
CallData = getMarketInfoCallData
|
||||
};
|
||||
var getMarketTokenPriceCallData = new GetMarketTokenPriceFunction
|
||||
{
|
||||
DataStore = Arbitrum.AddressV2.DataStore,
|
||||
Market = marketProps,
|
||||
IndexTokenPrice = marketPrices.IndexTokenPrice,
|
||||
LongTokenPrice = marketPrices.LongTokenPrice,
|
||||
ShortTokenPrice = marketPrices.ShortTokenPrice,
|
||||
PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS),
|
||||
Maximize = true
|
||||
}.GetCallData();
|
||||
var getMarketTokenPriceCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.Reader,
|
||||
CallData = getMarketTokenPriceCallData
|
||||
};
|
||||
var getMarketTokenPriceMinCallData = new GetMarketTokenPriceFunction
|
||||
{
|
||||
DataStore = Arbitrum.AddressV2.DataStore,
|
||||
Market = marketProps,
|
||||
IndexTokenPrice = marketPrices.IndexTokenPrice,
|
||||
LongTokenPrice = marketPrices.LongTokenPrice,
|
||||
ShortTokenPrice = marketPrices.ShortTokenPrice,
|
||||
PnlFactorType = _helpers.HashString(Constants.GMX.MAX_PNL_FACTOR_FOR_TRADERS),
|
||||
Maximize = false
|
||||
}.GetCallData();
|
||||
var getMarketTokenPriceMinCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.Reader,
|
||||
CallData = getMarketTokenPriceMinCallData
|
||||
};
|
||||
|
||||
var readerMulticall = new AggregateFunction();
|
||||
readerMulticall.Calls = new List<Call>();
|
||||
readerMulticall.Calls.Add(getMarketInfoCall);
|
||||
readerMulticall.Calls.Add(getMarketTokenPriceCall);
|
||||
readerMulticall.Calls.Add(getMarketTokenPriceMinCall);
|
||||
|
||||
var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();
|
||||
var readerCallResults = await queryHandler
|
||||
.QueryDeserializingToObjectAsync<AggregateOutputDTO>(readerMulticall, Arbitrum.AddressV2.Multicall)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var marketInfo = new GetMarketInfoOutputDTO().DecodeOutput(readerCallResults.ReturnData[0].ToHex());
|
||||
var marketTokenPriceMax =
|
||||
new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[1].ToHex());
|
||||
var marketTokenPriceMin =
|
||||
new GetMarketTokenPriceOutputDTO().DecodeOutput(readerCallResults.ReturnData[2].ToHex());
|
||||
|
||||
// Get hashed key to call datastore
|
||||
var marketKeys = GmxKeysService.GetMarketKeys(market.MarketToken);
|
||||
if (marketKeys == null)
|
||||
continue;
|
||||
|
||||
var longInterestUsingLongTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.LongInterestUsingLongToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var longInterestUsingLongTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = longInterestUsingLongTokenCallData
|
||||
};
|
||||
var longInterestUsingShortTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.LongInterestUsingShortToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var longInterestUsingShortTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = longInterestUsingShortTokenCallData
|
||||
};
|
||||
var shortInterestUsingLongTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.ShortInterestUsingLongToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var shortInterestUsingLongTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = shortInterestUsingLongTokenCallData
|
||||
};
|
||||
var shortInterestUsingShortTokenCallData = new GetUintFunction()
|
||||
{
|
||||
Key = marketKeys.ShortInterestUsingShortToken.HexToByteArray()
|
||||
}.GetCallData();
|
||||
var shortInterestUsingShortTokenCall = new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.DataStore,
|
||||
CallData = shortInterestUsingShortTokenCallData
|
||||
};
|
||||
|
||||
var dataStoreMulticall = new AggregateFunction();
|
||||
dataStoreMulticall.Calls = new List<Call>();
|
||||
dataStoreMulticall.Calls.Add(longInterestUsingLongTokenCall);
|
||||
dataStoreMulticall.Calls.Add(longInterestUsingShortTokenCall);
|
||||
dataStoreMulticall.Calls.Add(shortInterestUsingLongTokenCall);
|
||||
dataStoreMulticall.Calls.Add(shortInterestUsingShortTokenCall);
|
||||
|
||||
// Call datastore to get market info
|
||||
var dataStoreQueryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();
|
||||
var dataStoreCallResults = await dataStoreQueryHandler
|
||||
.QueryDeserializingToObjectAsync<AggregateOutputDTO>(dataStoreMulticall, Arbitrum.AddressV2.Multicall)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var marketInfos = GmxMappers.Map(marketInfo.ReturnValue1);
|
||||
readerResult.Add(new GmxMarketInfo()
|
||||
{
|
||||
Market = marketInfos,
|
||||
Infos = DecodeFundingRateOutput(dataStoreCallResults, marketInfos.IsSameCollaterals),
|
||||
MarketTokenPriceMax = GmxMappers.Map(marketTokenPriceMax),
|
||||
MarketTokenPriceMin = GmxMappers.Map(marketTokenPriceMin)
|
||||
});
|
||||
}
|
||||
|
||||
return readerResult;
|
||||
}
|
||||
|
||||
private GmxMarketInfos DecodeFundingRateOutput(AggregateOutputDTO results, bool isSameCollaterals)
|
||||
{
|
||||
var marketDivisor = new BigInteger(isSameCollaterals ? 2 : 1);
|
||||
var longInterestUsingLongToken =
|
||||
new GetUintOutputDTO().DecodeOutput(results.ReturnData[0].ToHex()).ReturnValue1 / marketDivisor;
|
||||
var longInterestUsingShortToken =
|
||||
new GetUintOutputDTO().DecodeOutput(results.ReturnData[1].ToHex()).ReturnValue1 / marketDivisor;
|
||||
var shortInterestUsingLongToken =
|
||||
new GetUintOutputDTO().DecodeOutput(results.ReturnData[2].ToHex()).ReturnValue1 / marketDivisor;
|
||||
var shortInterestUsingShortToken =
|
||||
new GetUintOutputDTO().DecodeOutput(results.ReturnData[3].ToHex()).ReturnValue1 / marketDivisor;
|
||||
|
||||
var longInterestUsd = longInterestUsingLongToken + longInterestUsingShortToken;
|
||||
var shortInterestUsd = shortInterestUsingLongToken + shortInterestUsingShortToken;
|
||||
|
||||
var marketInfos = new GmxMarketInfos()
|
||||
{
|
||||
LongInterestUsd = longInterestUsd,
|
||||
ShortInterestUsd = shortInterestUsd
|
||||
};
|
||||
return marketInfos;
|
||||
}
|
||||
|
||||
public async Task<List<GmxTokenData>> GetTokensData(Web3 web3)
|
||||
{
|
||||
var tokens = TokenV2Service.GetTokens().ToList();
|
||||
var balances = await GetTokenBalances(web3, tokens);
|
||||
var prices = GetTokenPrices(web3, tokens);
|
||||
var result = new List<GmxTokenData>();
|
||||
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
BigInteger? balance = null;
|
||||
if (balances.Balances != null && balances.Balances.ContainsKey(token.Address))
|
||||
{
|
||||
balance = balances.Balances[token.Address];
|
||||
}
|
||||
|
||||
var price = prices[token.Address].Price;
|
||||
|
||||
var data = new GmxTokenData()
|
||||
{
|
||||
Address = token.Address,
|
||||
Name = token.Name,
|
||||
Symbol = token.Symbol,
|
||||
Decimals = token.Decimals,
|
||||
Price = price,
|
||||
Balance = balance
|
||||
};
|
||||
result.Add(data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Dictionary<string, GmxTokenPriceData> GetTokenPrices(Web3 web3, List<GmxToken> tokens)
|
||||
{
|
||||
var result = new Dictionary<string, GmxTokenPriceData>();
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
// TODO fetch token price from oracle
|
||||
result.Add(token.Address, new GmxTokenPriceData()
|
||||
{
|
||||
Price = new MarketPrice()
|
||||
{
|
||||
Min = 0,
|
||||
Max = 0
|
||||
},
|
||||
Balance = 0,
|
||||
TotalSupply = 0
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<GmxTokenBalances> GetTokenBalances(Web3 web3, List<GmxToken> tokens, string? account = null)
|
||||
{
|
||||
var result = new GmxTokenBalances();
|
||||
result.Balances = new Dictionary<string, BigInteger>();
|
||||
var aggregateFunction = new AggregateFunction();
|
||||
aggregateFunction.Calls = new List<Call>();
|
||||
foreach (var token in tokens)
|
||||
{
|
||||
if (token.IsNative)
|
||||
{
|
||||
var nativeBalanceCallData = new GetEthBalanceFunction()
|
||||
{
|
||||
Addr = account ?? Nethereum.Util.AddressUtil.ZERO_ADDRESS
|
||||
}.GetCallData();
|
||||
aggregateFunction.Calls.Add(new Call
|
||||
{
|
||||
Target = Arbitrum.AddressV2.Multicall,
|
||||
CallData = nativeBalanceCallData
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var balanceCallData = new BalanceOfFunction()
|
||||
{
|
||||
Owner = account ?? GmxHelpers.GetRandomAddress()
|
||||
}.GetCallData();
|
||||
aggregateFunction.Calls.Add(new Call
|
||||
{
|
||||
Target = token.Address,
|
||||
CallData = balanceCallData
|
||||
});
|
||||
}
|
||||
|
||||
var queryHandler = web3.Eth.GetContractQueryHandler<AggregateFunction>();
|
||||
var returnCalls = await queryHandler
|
||||
.QueryDeserializingToObjectAsync<AggregateOutputDTO>(aggregateFunction, Arbitrum.AddressV2.Multicall)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var balances = new BalanceOfOutputDTOBase().DecodeOutput(returnCalls.ReturnData[0].ToHex());
|
||||
result.Balances.Add(token.Address, balances.Balance);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<FundingRate>> GetFundingRate(Web3 web3)
|
||||
{
|
||||
var market = await GetMarketInfo(web3);
|
||||
return Map(market);
|
||||
}
|
||||
|
||||
private List<FundingRate> Map(GmxMarketInfo market)
|
||||
{
|
||||
var longApr = GetFundingFactorPerPeriod(market, true, Periods[Enums.Timeframe.OneHour]) * 100;
|
||||
var shortApr = GetFundingFactorPerPeriod(market, false, Periods[Enums.Timeframe.OneHour]) * 100;
|
||||
var longFundingRate = new FundingRate()
|
||||
{
|
||||
Ticker = GmxHelpers.GetTicker(market.Market.Symbol),
|
||||
Rate = GmxHelpers.FormatAmount(longApr, 30, 4),
|
||||
Direction = Enums.TradeDirection.Long
|
||||
};
|
||||
var shortFundingRate = new FundingRate()
|
||||
{
|
||||
Ticker = GmxHelpers.GetTicker(market.Market.Symbol),
|
||||
Rate = GmxHelpers.FormatAmount(shortApr, 30, 4),
|
||||
Direction = Enums.TradeDirection.Short
|
||||
};
|
||||
return new List<FundingRate>() { longFundingRate, shortFundingRate };
|
||||
}
|
||||
|
||||
public async Task<List<FundingRate>> GetFundingRates(Web3 web3)
|
||||
{
|
||||
var fundingRates = new List<FundingRate>();
|
||||
var marketDatas = await GetMarketInfosAsync(web3);
|
||||
foreach (var gmxMarketInfo in marketDatas)
|
||||
{
|
||||
var rates = Map(gmxMarketInfo);
|
||||
fundingRates.AddRange(rates);
|
||||
}
|
||||
|
||||
return fundingRates;
|
||||
}
|
||||
|
||||
private BigInteger GetFundingFactorPerPeriod(GmxMarketInfo marketInfo, bool isLong, int periodInSeconds)
|
||||
{
|
||||
var fundingFactorPerSecond = marketInfo.Market.FundingFactorPerSecond;
|
||||
var longsPayShorts = marketInfo.Market.LongsPayShorts;
|
||||
var longInterestUsd = marketInfo.Infos.LongInterestUsd;
|
||||
var shortInterestUsd = marketInfo.Infos.ShortInterestUsd;
|
||||
|
||||
var isLargerSide = isLong ? longsPayShorts : !longsPayShorts;
|
||||
|
||||
BigInteger factorPerSecond;
|
||||
|
||||
if (isLargerSide)
|
||||
{
|
||||
factorPerSecond = fundingFactorPerSecond * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var largerInterestUsd = longsPayShorts ? longInterestUsd : shortInterestUsd;
|
||||
var smallerInterestUsd = longsPayShorts ? shortInterestUsd : longInterestUsd;
|
||||
|
||||
var ratio = smallerInterestUsd > 0
|
||||
? BigInteger.Multiply(largerInterestUsd, PRECISION) / smallerInterestUsd
|
||||
: 0;
|
||||
|
||||
factorPerSecond = ApplyFactor(ratio, fundingFactorPerSecond);
|
||||
}
|
||||
|
||||
return factorPerSecond * periodInSeconds;
|
||||
}
|
||||
|
||||
private BigInteger ApplyFactor(BigInteger ratio, BigInteger fundingFactorPerSecond)
|
||||
{
|
||||
// Implement the logic for applying the factor based on the ratio
|
||||
// This is a placeholder implementation
|
||||
return BigInteger.Multiply(ratio, fundingFactorPerSecond) / PRECISION;
|
||||
}
|
||||
|
||||
private static readonly BigInteger PRECISION = BigInteger.Pow(10, 18);
|
||||
|
||||
private Dictionary<Enums.Timeframe, int> Periods = new Dictionary<Enums.Timeframe, int>()
|
||||
{
|
||||
{ Enums.Timeframe.FiveMinutes, 300 },
|
||||
{ Enums.Timeframe.FifteenMinutes, 900 },
|
||||
{ Enums.Timeframe.OneHour, 3600 },
|
||||
{ Enums.Timeframe.FourHour, 14400 },
|
||||
{ Enums.Timeframe.OneDay, 86400 }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user