Skip to content

Commit

Permalink
fix(app): trade panel enhancements (#2798)
Browse files Browse the repository at this point in the history
Trade Panel Enhancements
  • Loading branch information
platschi authored Oct 4, 2023
2 parents 82000c0 + 0075fcf commit 7b24d94
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import InputTitle from 'components/Input/InputTitle'
import SLTPInputField, { SLTPInputFieldProps } from '../Trade/SLTPInputField'

const EditStopLossAndTakeProfitInput: React.FC<SLTPInputFieldProps> = memo(
({ type, currentPrice, ...props }) => {
({ type, price, ...props }) => {
const { t } = useTranslation()

return (
Expand All @@ -18,16 +18,16 @@ const EditStopLossAndTakeProfitInput: React.FC<SLTPInputFieldProps> = memo(
label={type === 'take-profit' ? 'Take Profit' : 'Stop Loss'}
rightElement={
<StyledInputTitle>
{t('futures.market.trade.edit-sl-tp.last-price')}:{' '}
<span>{formatDollars(currentPrice)}</span>
{t('futures.market.trade.edit-sl-tp.entry-price')}:{' '}
<span>{formatDollars(price)}</span>
</StyledInputTitle>
}
/>

<SLTPInputField
{...props}
type={type}
currentPrice={currentPrice}
price={price}
dataTestId={'trade-panel-stop-loss-input'}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function EditStopLossAndTakeProfitModal() {
const { t } = useTranslation()
const dispatch = useAppDispatch()
const transactionState = useAppSelector(selectTransaction)
const { market, marketPrice, position } = useAppSelector(selectEditPositionModalInfo)
const { market, position } = useAppSelector(selectEditPositionModalInfo)
const exsistingSLTPOrders = useAppSelector(selectAllSLTPOrders)
const isSubmitting = useAppSelector(selectSubmittingFuturesTx)
const { takeProfitPrice, stopLossPrice } = useAppSelector(selectSlTpModalInputs)
Expand Down Expand Up @@ -114,6 +114,18 @@ export default function EditStopLossAndTakeProfitModal() {
]
)

const entryPriceWei = useMemo(() => {
return position?.activePosition?.details?.entryPrice ?? wei(0)
}, [position?.activePosition?.details?.entryPrice])

const calculateSizeWei = useMemo(() => {
if (!position?.activePosition.size) {
return wei(0)
}

return position.activePosition.size.mul(entryPriceWei)
}, [position?.activePosition.size, entryPriceWei])

useEffect(() => {
const existingSL = exsistingSLTPOrders.find(
(o) => o.marketKey === market?.marketKey && o.orderType === ConditionalOrderTypeEnum.STOP
Expand Down Expand Up @@ -147,13 +159,13 @@ export default function EditStopLossAndTakeProfitModal() {
const relativePercent = wei(percent).div(leverageWei)
const stopLoss =
position?.activePosition.side === 'short'
? marketPrice.add(marketPrice.mul(relativePercent))
: marketPrice.sub(marketPrice.mul(relativePercent))
? entryPriceWei.add(entryPriceWei.mul(relativePercent))
: entryPriceWei.sub(entryPriceWei.mul(relativePercent))
const dp = suggestedDecimals(stopLoss)
dispatch(setSLTPModalStopLoss(stopLoss.toString(dp)))
}
},
[marketPrice, dispatch, position?.activePosition.side, leverageWei]
[entryPriceWei, dispatch, position?.activePosition.side, leverageWei]
)

const onSelectTakeProfit = useCallback(
Expand All @@ -166,13 +178,13 @@ export default function EditStopLossAndTakeProfitModal() {
const relativePercent = wei(percent).div(leverageWei)
const takeProfit =
position?.activePosition.side === 'short'
? marketPrice.sub(marketPrice.mul(relativePercent))
: marketPrice.add(marketPrice.mul(relativePercent))
? entryPriceWei.sub(entryPriceWei.mul(relativePercent))
: entryPriceWei.add(entryPriceWei.mul(relativePercent))
const dp = suggestedDecimals(takeProfit)
dispatch(setSLTPModalTakeProfit(takeProfit.toString(dp)))
}
},
[marketPrice, dispatch, position?.activePosition.side, leverageWei]
[entryPriceWei, dispatch, position?.activePosition.side, leverageWei]
)

const onChangeStopLoss = useCallback(
Expand Down Expand Up @@ -220,10 +232,11 @@ export default function EditStopLossAndTakeProfitModal() {
<EditStopLossAndTakeProfitInput
type={'take-profit'}
invalidLabel={sltpValidity.takeProfit.invalidLabel}
currentPrice={marketPrice}
price={entryPriceWei}
value={takeProfitPrice}
positionSide={position?.activePosition.side || PositionSide.LONG}
leverage={position?.activePosition.leverage || wei(1)}
size={calculateSizeWei}
onChange={onChangeTakeProfit}
/>

Expand All @@ -240,8 +253,9 @@ export default function EditStopLossAndTakeProfitModal() {
positionSide={position?.activePosition.side || PositionSide.LONG}
leverage={position?.activePosition.leverage || wei(1)}
invalidLabel={sltpValidity.stopLoss.invalidLabel}
currentPrice={marketPrice}
price={entryPriceWei}
value={stopLossPrice}
size={calculateSizeWei}
onChange={onChangeStopLoss}
/>

Expand Down
9 changes: 6 additions & 3 deletions packages/app/src/sections/futures/Trade/SLTPInputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ export type SLTPInputFieldProps = {
type: 'take-profit' | 'stop-loss'
value: string
invalidLabel: string | undefined
currentPrice: Wei
price: Wei
leverage: Wei
size: Wei
minMaxPrice?: Wei
dataTestId?: string
positionSide: PositionSide
Expand All @@ -27,9 +28,10 @@ const SLTPInputField: React.FC<SLTPInputFieldProps> = memo(
type,
value,
invalidLabel,
currentPrice,
price,
positionSide,
leverage,
size,
dataTestId,
disabledReason,
disabled,
Expand Down Expand Up @@ -59,9 +61,10 @@ const SLTPInputField: React.FC<SLTPInputFieldProps> = memo(
<ShowPercentage
targetPrice={value}
isStopLoss={type === 'stop-loss'}
currentPrice={currentPrice}
price={price}
leverageSide={positionSide}
leverageWei={leverage}
sizeWei={size}
/>
)
}
Expand Down
40 changes: 31 additions & 9 deletions packages/app/src/sections/futures/Trade/SLTPInputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ import {
selectLeverageInput,
selectLeverageSide,
selectTradePanelSLTPValidity,
selectTradeSizeInputs,
} from 'state/futures/selectors'
import {
setSmartMarginTradeStopLoss,
setSmartMarginTradeTakeProfit,
} from 'state/futures/smartMargin/reducer'
import { selectSlTpTradeInputs } from 'state/futures/smartMargin/selectors'
import {
selectOrderType,
selectSlTpTradeInputs,
selectSmartMarginOrderPrice,
} from 'state/futures/smartMargin/selectors'
import { useAppDispatch, useAppSelector } from 'state/hooks'

import OrderAcknowledgement from './OrderAcknowledgement'
Expand All @@ -39,6 +44,9 @@ export default function SLTPInputs() {
const leverage = useAppSelector(selectLeverageInput)
const hideWarning = useAppSelector(selectAckedOrdersWarning)
const sltpValidity = useSelector(selectTradePanelSLTPValidity)
const { susdSize } = useAppSelector(selectTradeSizeInputs)
const orderType = useAppSelector(selectOrderType)
const orderPrice = useAppSelector(selectSmartMarginOrderPrice)

const [showInputs, setShowInputs] = useState(false)
const [showOrderWarning, setShowOrderWarning] = useState(false)
Expand All @@ -56,19 +64,31 @@ export default function SLTPInputs() {
return leverage && Number(leverage) > 0 ? wei(leverage) : wei(1)
}, [leverage])

const price = useMemo(() => {
switch (orderType) {
case 'market':
return currentPrice
case 'limit':
case 'stop_market':
return orderPrice ? wei(orderPrice) : currentPrice
default:
return currentPrice
}
}, [orderPrice, orderType, currentPrice])

const onSelectStopLossPercent = useCallback(
(index: number) => {
const option = SL_OPTIONS[index]
const percent = Math.abs(Number(option.replace('%', ''))) / 100
const relativePercent = wei(percent).div(leverageWei)
const stopLoss =
leverageSide === 'short'
? currentPrice.add(currentPrice.mul(relativePercent))
: currentPrice.sub(currentPrice.mul(relativePercent))
? price.add(price.mul(relativePercent))
: price.sub(price.mul(relativePercent))
const dp = suggestedDecimals(stopLoss)
dispatch(setSmartMarginTradeStopLoss(stopLoss.toString(dp)))
},
[currentPrice, dispatch, leverageSide, leverageWei]
[dispatch, leverageSide, leverageWei, price]
)

const onSelectTakeProfit = useCallback(
Expand All @@ -78,12 +98,12 @@ export default function SLTPInputs() {
const relativePercent = wei(percent).div(leverageWei)
const takeProfit =
leverageSide === 'short'
? currentPrice.sub(currentPrice.mul(relativePercent))
: currentPrice.add(currentPrice.mul(relativePercent))
? price.sub(price.mul(relativePercent))
: price.add(price.mul(relativePercent))
const dp = suggestedDecimals(takeProfit)
dispatch(setSmartMarginTradeTakeProfit(takeProfit.toString(dp)))
},
[currentPrice, dispatch, leverageSide, leverageWei]
[dispatch, leverageSide, leverageWei, price]
)

const onChangeStopLoss = useCallback(
Expand Down Expand Up @@ -133,11 +153,12 @@ export default function SLTPInputs() {
invalidLabel={sltpValidity.takeProfit.invalidLabel}
value={takeProfitPrice}
type={'take-profit'}
currentPrice={currentPrice}
price={price}
positionSide={leverageSide}
leverage={leverageWei}
dataTestId={'trade-panel-take-profit-input'}
onChange={onChangeTakeProfit}
size={susdSize}
/>

<Spacer height={12} />
Expand All @@ -153,11 +174,12 @@ export default function SLTPInputs() {
invalidLabel={sltpValidity.stopLoss.invalidLabel}
value={stopLossPrice}
type={'stop-loss'}
currentPrice={currentPrice}
price={price}
positionSide={leverageSide}
leverage={leverageWei}
dataTestId={'trade-panel-stop-loss-input'}
onChange={onChangeStopLoss}
size={susdSize}
/>
</InputsContainer>
)
Expand Down
38 changes: 27 additions & 11 deletions packages/app/src/sections/futures/Trade/ShowPercentage.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,61 @@
import { PositionSide } from '@kwenta/sdk/types'
import { formatPercent } from '@kwenta/sdk/utils'
import { formatPercent, formatDollars } from '@kwenta/sdk/utils'
import Wei, { wei } from '@synthetixio/wei'
import { useMemo } from 'react'
import styled from 'styled-components'

import { Body } from 'components/Text'

type ShowPercentageProps = {
targetPrice: string
isStopLoss?: boolean
currentPrice: Wei
price: Wei
leverageSide: PositionSide | string | undefined
leverageWei: Wei
sizeWei: Wei
}

const ShowPercentage: React.FC<ShowPercentageProps> = ({
targetPrice,
isStopLoss = false,
currentPrice,
price,
leverageSide,
leverageWei,
sizeWei,
}) => {
const calculatePercentage = useMemo(() => {
if (!targetPrice || !currentPrice || !leverageSide) return ''
const [calculatePercentage, calculatePL] = useMemo(() => {
if (!targetPrice || !price || !leverageSide || !sizeWei) return ''
const priceWei = wei(targetPrice)

const diff =
leverageSide === 'short'
? isStopLoss
? priceWei.sub(currentPrice)
: currentPrice.sub(priceWei)
? priceWei.sub(price)
: price.sub(priceWei)
: isStopLoss
? currentPrice.sub(priceWei)
: priceWei.sub(currentPrice)
? price.sub(priceWei)
: priceWei.sub(price)

const percentage = diff.div(price).mul(leverageWei)
const profitLoss = sizeWei.mul(percentage.div(leverageWei)).mul(isStopLoss ? -1 : 1)

return formatPercent(diff.div(currentPrice).mul(leverageWei))
}, [currentPrice, isStopLoss, leverageSide, leverageWei, targetPrice])
return [formatPercent(percentage), formatDollars(profitLoss, { sign: isStopLoss ? '' : '+' })]
}, [price, isStopLoss, leverageSide, leverageWei, targetPrice, sizeWei])

return (
<Body size="large" mono>
<ProfitLoss isStopLoss={isStopLoss}>{calculatePL}</ProfitLoss>
{calculatePercentage}
</Body>
)
}

const ProfitLoss = styled.span<{ isStopLoss: boolean }>`
margin-right: 0.7rem;
color: ${({ theme, isStopLoss }) =>
isStopLoss
? theme.colors.selectedTheme.newTheme.text.negative
: theme.colors.selectedTheme.newTheme.text.positive};
`

export default ShowPercentage
2 changes: 1 addition & 1 deletion packages/app/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@
"no-tp": "No TP",
"no-sl": "No SL",
"stop-loss": "Stop Loss",
"last-price": "Last Price",
"entry-price": "Entry Price",
"estimated-profit": "Estimated Profit",
"estimated-loss": "Estimated Loss",
"warning": "This setting applies to the entire position."
Expand Down

0 comments on commit 7b24d94

Please sign in to comment.