feat(trading): add risk factors leverage and update accordion panel (#5000)

Co-authored-by: Rado <szpiechrados@gmail.com>
This commit is contained in:
m.ray 2023-10-11 12:19:43 +03:00 committed by GitHub
parent 4968b537b8
commit 0d14722c5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 211 additions and 96 deletions

View File

@ -3,6 +3,7 @@ import type { MarketInfoWithData } from '@vegaprotocol/markets';
import { import {
LiquidityPriceRangeInfoPanel, LiquidityPriceRangeInfoPanel,
LiquiditySLAParametersInfoPanel, LiquiditySLAParametersInfoPanel,
MarginScalingFactorsPanel,
PriceMonitoringBoundsInfoPanel, PriceMonitoringBoundsInfoPanel,
SuccessionLineInfoPanel, SuccessionLineInfoPanel,
getDataSourceSpecForSettlementData, getDataSourceSpecForSettlementData,
@ -17,7 +18,6 @@ import {
OracleInfoPanel, OracleInfoPanel,
RiskFactorsInfoPanel, RiskFactorsInfoPanel,
RiskModelInfoPanel, RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
} from '@vegaprotocol/markets'; } from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/markets'; import { MarketInfoTable } from '@vegaprotocol/markets';
@ -69,8 +69,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
<MetadataInfoPanel market={market} /> <MetadataInfoPanel market={market} />
<h2 className={headerClassName}>{t('Risk model')}</h2> <h2 className={headerClassName}>{t('Risk model')}</h2>
<RiskModelInfoPanel market={market} /> <RiskModelInfoPanel market={market} />
<h2 className={headerClassName}>{t('Risk parameters')}</h2> <h2 className={headerClassName}>{t('Margin scaling factors')}</h2>
<RiskParametersInfoPanel market={market} /> <MarginScalingFactorsPanel market={market} />
<h2 className={headerClassName}>{t('Risk factors')}</h2> <h2 className={headerClassName}>{t('Risk factors')}</h2>
<RiskFactorsInfoPanel market={market} /> <RiskFactorsInfoPanel market={market} />
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => ( {(market.data?.priceMonitoringBounds || []).map((trigger, i) => (

View File

@ -12,12 +12,12 @@ import {
PriceMonitoringBoundsInfoPanel, PriceMonitoringBoundsInfoPanel,
RiskFactorsInfoPanel, RiskFactorsInfoPanel,
RiskModelInfoPanel, RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
getDataSourceSpecForSettlementSchedule, getDataSourceSpecForSettlementSchedule,
getDataSourceSpecForSettlementData, getDataSourceSpecForSettlementData,
getDataSourceSpecForTradingTermination, getDataSourceSpecForTradingTermination,
getSigners, getSigners,
MarginScalingFactorsPanel,
} from '@vegaprotocol/markets'; } from '@vegaprotocol/markets';
import { import {
Button, Button,
@ -219,8 +219,10 @@ export const ProposalMarketData = ({
parentMarket={parentMarketData} parentMarket={parentMarketData}
/> />
<h2 className={marketDataHeaderStyles}>{t('Risk parameters')}</h2> <h2 className={marketDataHeaderStyles}>
<RiskParametersInfoPanel {t('Margin scaling factors')}
</h2>
<MarginScalingFactorsPanel
market={marketData} market={marketData}
parentMarket={parentMarketData} parentMarket={parentMarketData}
/> />

View File

@ -138,6 +138,8 @@ query MarketInfo($marketId: ID!) {
positionDecimalPlaces positionDecimalPlaces
state state
tradingMode tradingMode
linearSlippageFactor
quadraticSlippageFactor
proposal { proposal {
id id
rationale { rationale {

File diff suppressed because one or more lines are too long

View File

@ -44,8 +44,6 @@ export const Row = ({
// a specific parentValue is missing. These values are only used when we // a specific parentValue is missing. These values are only used when we
// have successor market parent data. // have successor market parent data.
const className = 'text-sm';
const getFormattedValue = (value: ReactNode) => { const getFormattedValue = (value: ReactNode) => {
if (typeof value !== 'string' && typeof value !== 'number') return value; if (typeof value !== 'string' && typeof value !== 'number') return value;
if (unformatted || isNaN(Number(value))) { if (unformatted || isNaN(Number(value))) {
@ -75,8 +73,8 @@ export const Row = ({
key={field} key={field}
inline={true} inline={true}
noBorder={noBorder} noBorder={noBorder}
dtClassName={className} dtClassName="text-xs"
ddClassName={className} ddClassName="text-xs"
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Tooltip description={tooltipMapping[field]} align="start"> <Tooltip description={tooltipMapping[field]} align="start">

View File

@ -32,6 +32,7 @@ import {
LiquidityMonitoringParametersInfoPanel, LiquidityMonitoringParametersInfoPanel,
LiquidityPriceRangeInfoPanel, LiquidityPriceRangeInfoPanel,
LiquiditySLAParametersInfoPanel, LiquiditySLAParametersInfoPanel,
MarginScalingFactorsPanel,
MarketPriceInfoPanel, MarketPriceInfoPanel,
MarketVolumeInfoPanel, MarketVolumeInfoPanel,
MetadataInfoPanel, MetadataInfoPanel,
@ -39,7 +40,6 @@ import {
PriceMonitoringBoundsInfoPanel, PriceMonitoringBoundsInfoPanel,
RiskFactorsInfoPanel, RiskFactorsInfoPanel,
RiskModelInfoPanel, RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
SuccessionLineInfoPanel, SuccessionLineInfoPanel,
} from './market-info-panels'; } from './market-info-panels';
@ -236,9 +236,9 @@ export const MarketInfoAccordion = ({
content={<RiskModelInfoPanel market={market} />} content={<RiskModelInfoPanel market={market} />}
/> />
<AccordionItem <AccordionItem
itemId="risk-parameters" itemId="margin-scaling-factors"
title={t('Risk parameters')} title={t('Margin scaling factors')}
content={<RiskParametersInfoPanel market={market} />} content={<MarginScalingFactorsPanel market={market} />}
/> />
<AccordionItem <AccordionItem
itemId="risk-factors" itemId="risk-factors"

View File

@ -45,6 +45,7 @@ import type {
} from '@vegaprotocol/types'; } from '@vegaprotocol/types';
import { import {
ConditionOperatorMapping, ConditionOperatorMapping,
MarketStateMapping,
MarketTradingModeMapping, MarketTradingModeMapping,
} from '@vegaprotocol/types'; } from '@vegaprotocol/types';
import { import {
@ -220,58 +221,78 @@ export const KeyDetailsInfoPanel = ({
const assetDecimals = getAsset(market).decimals; const assetDecimals = getAsset(market).decimals;
return ( return (
<MarketInfoTable <>
data={ <KeyValueTable>
FLAGS.SUCCESSOR_MARKETS <KeyValueTableRow noBorder>
? { <div>{t('Market ID')}</div>
name: market.tradableInstrument.instrument.name, <CopyWithTooltip text={market.id}>
marketID: market.id, <button
parentMarketID: parentMarketIdData?.market?.parentMarketID || '-', data-testid="copy-eth-oracle-address"
insurancePoolFraction: className="uppercase text-right"
(successorProposalDetails?.proposal?.terms.change.__typename === >
'NewMarket' && <span className="flex gap-1">
successorProposalDetails.proposal.terms.change {truncateMiddle(market.id)}
.successorConfiguration?.insurancePoolFraction) || <VegaIcon name={VegaIconNames.COPY} size={16} />
'-', </span>
tradingMode: </button>
market.tradingMode && </CopyWithTooltip>
MarketTradingModeMapping[market.tradingMode], </KeyValueTableRow>
marketDecimalPlaces: market.decimalPlaces, </KeyValueTable>
positionDecimalPlaces: market.positionDecimalPlaces, <MarketInfoTable
settlementAssetDecimalPlaces: assetDecimals, data={
} FLAGS.SUCCESSOR_MARKETS
: { ? {
name: market.tradableInstrument.instrument.name, name: market.tradableInstrument.instrument.name,
marketID: market.id, parentMarketID:
tradingMode: parentMarketIdData?.market?.parentMarketID || '-',
market.tradingMode && insurancePoolFraction:
MarketTradingModeMapping[market.tradingMode], (successorProposalDetails?.proposal?.terms.change
marketDecimalPlaces: market.decimalPlaces, .__typename === 'NewMarket' &&
positionDecimalPlaces: market.positionDecimalPlaces, successorProposalDetails.proposal.terms.change
settlementAssetDecimalPlaces: assetDecimals, .successorConfiguration?.insurancePoolFraction) ||
} '-',
} status: market.state && MarketStateMapping[market.state],
parentData={ tradingMode:
parentMarket && { market.tradingMode &&
name: parentMarket?.tradableInstrument?.instrument?.name, MarketTradingModeMapping[market.tradingMode],
marketID: parentMarket?.id, marketDecimalPlaces: market.decimalPlaces,
parentMarketID: grandparentMarketIdData?.market?.parentMarketID, positionDecimalPlaces: market.positionDecimalPlaces,
insurancePoolFraction: settlementAssetDecimalPlaces: assetDecimals,
parentSuccessorProposalDetails?.proposal?.terms.change }
.__typename === 'NewMarket' && : {
parentSuccessorProposalDetails.proposal.terms.change name: market.tradableInstrument.instrument.name,
.successorConfiguration?.insurancePoolFraction, status: market.state && MarketStateMapping[market.state],
tradingMode: tradingMode:
parentMarket?.tradingMode && market.tradingMode &&
MarketTradingModeMapping[ MarketTradingModeMapping[market.tradingMode],
parentMarket.tradingMode as MarketTradingMode marketDecimalPlaces: market.decimalPlaces,
], positionDecimalPlaces: market.positionDecimalPlaces,
marketDecimalPlaces: parentMarket?.decimalPlaces, settlementAssetDecimalPlaces: assetDecimals,
positionDecimalPlaces: parentMarket?.positionDecimalPlaces, }
settlementAssetDecimalPlaces: assetDecimals,
} }
} parentData={
/> parentMarket && {
name: parentMarket?.tradableInstrument?.instrument?.name,
parentMarketID: grandparentMarketIdData?.market?.parentMarketID,
insurancePoolFraction:
parentSuccessorProposalDetails?.proposal?.terms.change
.__typename === 'NewMarket' &&
parentSuccessorProposalDetails.proposal.terms.change
.successorConfiguration?.insurancePoolFraction,
status:
parentMarket?.state && MarketStateMapping[parentMarket.state],
tradingMode:
parentMarket?.tradingMode &&
MarketTradingModeMapping[
parentMarket.tradingMode as MarketTradingMode
],
marketDecimalPlaces: parentMarket?.decimalPlaces,
positionDecimalPlaces: parentMarket?.positionDecimalPlaces,
settlementAssetDecimalPlaces: assetDecimals,
}
}
/>
</>
); );
}; };
@ -432,8 +453,8 @@ export const SettlementAssetInfoPanel = ({ market }: MarketInfoProps) => {
asset={asset} asset={asset}
inline={true} inline={true}
noBorder={true} noBorder={true}
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal" dtClassName="text-black dark:text-white text-ui !px-0 text-xs"
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full" ddClassName="text-black dark:text-white text-ui !px-0 max-w-full text-xs"
/> />
<p className="mt-4 text-xs"> <p className="mt-4 text-xs">
{t( {t(
@ -505,18 +526,53 @@ export const RiskModelInfoPanel = ({
} }
return ( return (
<MarketInfoTable <>
data={{ tau, riskAversionParameter }} <MarketInfoTable
parentData={parentData} data={{ tau, riskAversionParameter }}
unformatted parentData={parentData}
/> unformatted
/>
<RiskParametersInfoPanel market={market} parentMarket={parentMarket} />
</>
); );
}; };
export const RiskParametersInfoPanel = ({ export const MarginScalingFactorsPanel = ({
market, market,
parentMarket, parentMarket,
}: MarketInfoProps) => { }: MarketInfoProps) => {
const data = {
linearSlippageFactor: market.linearSlippageFactor,
quadraticSlippageFactor: market.quadraticSlippageFactor,
searchLevel:
market.tradableInstrument.marginCalculator?.scalingFactors.searchLevel,
initialMargin:
market.tradableInstrument.marginCalculator?.scalingFactors.initialMargin,
collateralRelease:
market.tradableInstrument.marginCalculator?.scalingFactors
.collateralRelease,
};
const parentData = parentMarket
? {
linearSlippageFactor: parentMarket?.linearSlippageFactor,
quadraticSlippageFactor: parentMarket?.quadraticSlippageFactor,
searchLevel:
parentMarket?.tradableInstrument.marginCalculator?.scalingFactors
.searchLevel,
initialMargin:
parentMarket?.tradableInstrument.marginCalculator?.scalingFactors
.initialMargin,
collateralRelease:
parentMarket?.tradableInstrument.marginCalculator?.scalingFactors
.collateralRelease,
}
: undefined;
return <MarketInfoTable data={data} parentData={parentData} unformatted />;
};
const RiskParametersInfoPanel = ({ market, parentMarket }: MarketInfoProps) => {
const marketType = market.tradableInstrument.riskModel.__typename; const marketType = market.tradableInstrument.riskModel.__typename;
let data, parentData; let data, parentData;
@ -562,27 +618,66 @@ export const RiskFactorsInfoPanel = ({
market, market,
parentMarket, parentMarket,
}: MarketInfoProps) => { }: MarketInfoProps) => {
if (!market.riskFactors) { const getLeverageFactors = (market: MarketInfo) => {
return null; if (!market.riskFactors) {
} return undefined;
}
const { short, long } = market.riskFactors; const { short, long } = market.riskFactors;
let parentData; const maxLeverageLong = new BigNumber(1).dividedBy(
new BigNumber(market.linearSlippageFactor).plus(long)
);
if (parentMarket?.riskFactors) { const maxLeverageShort = new BigNumber(1).dividedBy(
const parentShort = parentMarket.riskFactors.short; new BigNumber(market.linearSlippageFactor).plus(short)
const parentLong = parentMarket.riskFactors.long; );
parentData = { short: parentShort, long: parentLong };
}
return ( const maxInitialLeverageLong = !market.tradableInstrument.marginCalculator
<MarketInfoTable ? undefined
data={{ short, long }} : new BigNumber(1)
parentData={parentData} .dividedBy(
unformatted market.tradableInstrument.marginCalculator.scalingFactors
/> .initialMargin
); )
.times(maxLeverageLong);
const maxInitialLeverageShort = !market.tradableInstrument.marginCalculator
? undefined
: new BigNumber(1)
.dividedBy(
market.tradableInstrument.marginCalculator.scalingFactors
.initialMargin
)
.times(maxLeverageShort);
const formatValue = (number: BigNumber | string | undefined) => {
if (!number) return undefined;
const value = new BigNumber(number);
if (value.gte(10)) {
return value.toFixed(3);
} else {
return value.toFixed(5);
}
};
const data = {
long: formatValue(long),
short: formatValue(short),
maxLeverageLong: formatValue(maxLeverageLong),
maxLeverageShort: formatValue(maxLeverageShort),
maxInitialLeverageLong: formatValue(maxInitialLeverageLong),
maxInitialLeverageShort: formatValue(maxInitialLeverageShort),
};
return data;
};
const data = getLeverageFactors(market);
const parentData = parentMarket
? getLeverageFactors(parentMarket)
: undefined;
return <MarketInfoTable data={data} parentData={parentData} unformatted />;
}; };
export const PriceMonitoringBoundsInfoPanel = ({ export const PriceMonitoringBoundsInfoPanel = ({

View File

@ -23,6 +23,8 @@ export const marketInfoQuery = (
description: '', description: '',
}, },
}, },
linearSlippageFactor: '0.01',
quadraticSlippageFactor: '0.0001',
marketTimestamps: { marketTimestamps: {
__typename: 'MarketTimestamps', __typename: 'MarketTimestamps',
open: '2022-11-15T02:15:24.543614154Z', open: '2022-11-15T02:15:24.543614154Z',

View File

@ -74,9 +74,13 @@ export const KeyValueTableRow = ({
{ 'flex-row items-center': inline }, { 'flex-row items-center': inline },
className className
); );
const dtClassNames = `break-words ${dtClassName}`; const dtClassNames = classNames(
'break-words',
dtClassName,
'text-neutral-500 dark:text-neutral-300'
);
const ddClassNames = classNames( const ddClassNames = classNames(
'break-words text-neutral-500 dark:text-neutral-300', 'break-words',
{ {
'font-mono': numerical, 'font-mono': numerical,
}, },

View File

@ -90,12 +90,22 @@ When I look into market info I **Must** see following specification:
- Risk model: (<a name="6002-MDET-209" href="#6002-MDET-209">6002-MDET-209</a>) - Risk model: (<a name="6002-MDET-209" href="#6002-MDET-209">6002-MDET-209</a>)
- Tau - Tau
- Risk Aversion Parameter - Risk Aversion Parameter
- Risk parameters: (<a name="6002-MDET-210" href="#6002-MDET-210">6002-MDET-210</a>) - R
- Sigma - Sigma
- Margin scaling factors (<a name="6002-MDET-210" href="#6002-MDET-210">6002-MDET-210</a>)
- Linear Slippage Factor
- Quadratic Slippage Factor
- Search Level
- Initial Margin
- Collateral Release
- Risk factors: (<a name="6002-MDET-211" href="#6002-MDET-211">6002-MDET-211</a>) - Risk factors: (<a name="6002-MDET-211" href="#6002-MDET-211">6002-MDET-211</a>)
- Short
- Long - Long
- price monitoring bounds <i>(multiple bounds possible)</i>: (<a name="6002-MDET-212" href="#6002-MDET-212">6002-MDET-212</a>) - Short
- Max Leverage Long
- Max Leverage Short
- Max Initial Leverage Long
- Max Initial Leverage Short
- Price monitoring bounds <i>(multiple bounds possible)</i>: (<a name="6002-MDET-212" href="#6002-MDET-212">6002-MDET-212</a>)
- Highest Price - Highest Price
- Lowest Price - Lowest Price
- Liquidity monitoring parameters: (<a name="6002-MDET-213" href="#6002-MDET-213">6002-MDET-213</a>) - Liquidity monitoring parameters: (<a name="6002-MDET-213" href="#6002-MDET-213">6002-MDET-213</a>)