feat(markets): add trading calculator tool and optimize app config
1. 新增工具箱页面和A股交易计算工具 2. 配置expo项目信息与eas构建参数 3. 清理无用的worklets依赖
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
// ===== 工具箱:交易计算 =====
|
||||
const calcState = {
|
||||
direction: 'up'
|
||||
}
|
||||
|
||||
const updateCalcSign = () => {
|
||||
const signEl = document.getElementById('calc-sign-display')
|
||||
if (!signEl) return
|
||||
const radios = document.querySelectorAll('input[name="calc-direction"]')
|
||||
radios.forEach(r => {
|
||||
if (r.checked) calcState.direction = r.value
|
||||
})
|
||||
if (calcState.direction === 'up') {
|
||||
signEl.textContent = '+'
|
||||
signEl.className = 'calc-sign-display is-up'
|
||||
} else {
|
||||
signEl.textContent = '-'
|
||||
signEl.className = 'calc-sign-display is-down'
|
||||
}
|
||||
}
|
||||
|
||||
const getCalcAmount = () => {
|
||||
const inputEl = document.getElementById('calc-amount-input')
|
||||
const selectEl = document.getElementById('calc-amount-select')
|
||||
const inputValue = inputEl ? parseFloat(inputEl.value) : NaN
|
||||
if (Number.isFinite(inputValue) && inputValue > 0) return inputValue
|
||||
const selectValue = selectEl ? parseFloat(selectEl.value) : NaN
|
||||
return Number.isFinite(selectValue) ? selectValue : 0
|
||||
}
|
||||
|
||||
// A 股费率:佣金万 1.0,最低 5 元
|
||||
const calcCommission = amount => {
|
||||
const rate = 0.0001
|
||||
const fee = amount * rate
|
||||
return Math.max(fee, 5)
|
||||
}
|
||||
|
||||
// 过户费:万 0.1
|
||||
const calcTransferFee = amount => {
|
||||
return amount * 0.00001
|
||||
}
|
||||
|
||||
// 印花税:卖出 0.1%
|
||||
const calcStampTax = amount => {
|
||||
return amount * 0.001
|
||||
}
|
||||
|
||||
const doTradeCalc = () => {
|
||||
const priceEl = document.getElementById('calc-price')
|
||||
const sharesEl = document.getElementById('calc-shares')
|
||||
const resultPriceEl = document.getElementById('calc-result-price')
|
||||
const resultFeeEl = document.getElementById('calc-result-fee')
|
||||
const resultSharesEl = document.getElementById('calc-result-shares')
|
||||
const buyAmountEl = document.getElementById('calc-buy-amount')
|
||||
const sellAmountEl = document.getElementById('calc-sell-amount')
|
||||
const diffEl = document.getElementById('calc-diff')
|
||||
|
||||
const price = priceEl ? parseFloat(priceEl.value) : NaN
|
||||
const shares = sharesEl ? parseFloat(sharesEl.value) : NaN
|
||||
|
||||
if (!Number.isFinite(price) || price <= 0 || !Number.isFinite(shares) || shares <= 0) {
|
||||
if (resultPriceEl) resultPriceEl.value = ''
|
||||
if (resultFeeEl) resultFeeEl.value = ''
|
||||
if (resultSharesEl) resultSharesEl.value = ''
|
||||
if (buyAmountEl) buyAmountEl.value = ''
|
||||
if (sellAmountEl) sellAmountEl.value = ''
|
||||
if (diffEl) diffEl.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const amount = getCalcAmount()
|
||||
if (amount <= 0) return
|
||||
|
||||
const sign = calcState.direction === 'up' ? 1 : -1
|
||||
const theoreticalPrice = price * (1 + sign * amount / 100)
|
||||
|
||||
if (theoreticalPrice <= 0) {
|
||||
if (resultPriceEl) resultPriceEl.value = ''
|
||||
if (resultFeeEl) resultFeeEl.value = ''
|
||||
if (resultSharesEl) resultSharesEl.value = ''
|
||||
if (buyAmountEl) buyAmountEl.value = ''
|
||||
if (sellAmountEl) sellAmountEl.value = ''
|
||||
if (diffEl) diffEl.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const buyAmountVal = price * shares
|
||||
const sellAmountVal = theoreticalPrice * shares
|
||||
|
||||
const buyCommission = calcCommission(buyAmountVal)
|
||||
const buyTransferFee = calcTransferFee(buyAmountVal)
|
||||
|
||||
const sellCommission = calcCommission(sellAmountVal)
|
||||
const sellTransferFee = calcTransferFee(sellAmountVal)
|
||||
const sellStampTax = calcStampTax(sellAmountVal)
|
||||
|
||||
const totalFees = buyCommission + buyTransferFee + sellCommission + sellTransferFee + sellStampTax
|
||||
|
||||
// 差额 = 卖出金额 - 买入金额 - 交易费
|
||||
const diff = sellAmountVal - buyAmountVal - totalFees
|
||||
|
||||
if (resultPriceEl) resultPriceEl.value = theoreticalPrice.toFixed(3)
|
||||
if (resultFeeEl) resultFeeEl.value = totalFees.toFixed(2)
|
||||
if (resultSharesEl) resultSharesEl.value = shares
|
||||
if (buyAmountEl) buyAmountEl.value = buyAmountVal.toFixed(2)
|
||||
if (sellAmountEl) sellAmountEl.value = sellAmountVal.toFixed(2)
|
||||
if (diffEl) diffEl.value = diff.toFixed(2)
|
||||
}
|
||||
|
||||
// ===== 工具箱初始化 =====
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// 幅度符号更新
|
||||
const amountSelect = document.getElementById('calc-amount-select')
|
||||
const amountInput = document.getElementById('calc-amount-input')
|
||||
if (amountSelect) amountSelect.addEventListener('change', updateCalcSign)
|
||||
if (amountInput) amountInput.addEventListener('input', updateCalcSign)
|
||||
const directionRadios = document.querySelectorAll('input[name="calc-direction"]')
|
||||
directionRadios.forEach(r => r.addEventListener('change', updateCalcSign))
|
||||
updateCalcSign()
|
||||
|
||||
// 计算按钮
|
||||
const btnCalc = document.getElementById('btn-calc')
|
||||
if (btnCalc) btnCalc.addEventListener('click', doTradeCalc)
|
||||
})
|
||||
Reference in New Issue
Block a user