import { computed, toRefs, shallowReadonly } from 'vue' import { v4 } from 'uuid' import { formatDecimal } from '@/filters' import { BuyOrSell } from '@/constants/buyorsell' import { queryTaAccounts } from '@/services/api/account' import { queryErmcpTradePosition } from '@/services/api/trade' import subscribe from '@/services/subscribe' import { useLoginStore } from './login' import { useFuturesStore } from './futures' import { VueStore } from '../base' import eventBus from '@/services/bus' interface StoreState { loading: boolean; accountId: number; // 当前资金账户ID accountList: Ermcp.TaAccountsRsp[]; // 资金账户列表 accountPositionList: Ermcp.TradePositionRsp[]; // 资金账户持仓列表 } function useFormula(item: Ermcp.TradePositionRsp) { const { getGoodsPriceByCode } = useFuturesStore() const { goodscode, buyorsell, curpositionqty, agreeunit, positionpl, opencost, positioncost, decimalplace } = item // 计算开仓均价 const calcOpenAveragePrice = () => { // 开仓成本 ÷ 期末头寸 ÷ 合约单位 return opencost / curpositionqty / agreeunit } // 计算持仓均价 const calcPositionAveragePrice = () => { // 持仓成本 ÷ 期末头寸 ÷ 合约单位 return positioncost / curpositionqty / agreeunit } // 计算浮动盈亏 - 对应市场收益权 const calcProfitLoss = () => { const last = getGoodsPriceByCode(goodscode) let result = positionpl if (last.value) { const positionAveragePrice = calcPositionAveragePrice() // 收益权 = (最新价 - 持仓均价) * 持仓数量 * 合约单位 * 方向(买1卖-1) const rightToEarnings = (last.value - positionAveragePrice) * curpositionqty * agreeunit result = rightToEarnings * (buyorsell === BuyOrSell.Buy ? 1 : -1) } return formatDecimal(result, decimalplace) } return { calcOpenAveragePrice, calcPositionAveragePrice, calcProfitLoss } } /** * 账户存储类 */ const store = new (class extends VueStore{ constructor() { const state: StoreState = { loading: false, accountId: 0, accountList: [], accountPositionList: [], } super(state) // 接收资金变动通知 eventBus.$on('MoneyChangedNotify', () => { this.actions.getAccountList() }) } private uuid = v4() private pending = Promise.resolve() // 请求等待状态,防止重复请求 /** 当前资金账户信息 */ private accountInfo = computed(() => { const account = this.state.accountList.find((e) => e.accountid === this.state.accountId) // 总浮动盈亏 const totalProfitLoss = this.futuresPositionList.value.reduce((res, cur) => res + cur.positionpl, 0) return { ...account, totalProfitLoss, } }) /** 期货持仓列表 */ private futuresPositionList = computed(() => { const positionList = this.state.accountPositionList return positionList.reduce((res, item) => { const { calcProfitLoss } = useFormula(item) res.push({ ...item, positionpl: Number(calcProfitLoss()), }) return res }, [] as Ermcp.TradePositionRsp[]) }) getters = { accountInfo: this.accountInfo, futuresPositionList: this.futuresPositionList } actions = { /** 获取资金账户列表 */ getAccountList: async () => { await this.pending const { getLoginId } = useLoginStore() this.state.loading = true this.pending = queryTaAccounts({ data: { loginID: getLoginId() }, success: (res) => { const dataList = res.data if (dataList.length) { this.state.accountList = dataList // 查找当前选中的资金账户 const account = dataList.find((e) => e.accountid === this.state.accountId) if (account) { this.state.loading = false } else { // 如果不存在,默认选中第一个账户 this.state.accountId = dataList[0].accountid this.actions.getAccountPositionList() } } else { this.state.loading = false this.actions.reset() } }, fail: () => { this.state.loading = false } }) return this.pending }, /** 获取资金账户持仓列表 */ getAccountPositionList: async (marketID?: number) => { await this.pending subscribe.removeQuoteSubscribe(this.uuid) this.state.loading = true this.pending = queryErmcpTradePosition({ data: { accountID: this.state.accountId, ...marketID ? { marketID } : {} }, success: (res) => { const codes = res.data.map((e) => e.goodscode) this.state.accountPositionList = res.data if (codes.length) { // 行情订阅 subscribe.addQuoteSubscribe(codes, this.uuid).start() } }, complete: () => { this.state.loading = false } }) return this.pending }, /** 重置数据 */ reset: () => { this.state.accountId = 0 this.state.accountList = [] this.state.accountPositionList = [] } } }) export function useAccountStore() { return shallowReadonly({ ...toRefs(store.state), ...store.getters, ...store.actions, ...store.methods, }) }