account.ts 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import { toRefs, computed, reactive } from 'vue'
  2. import { isMatch } from 'lodash'
  3. import { queryTaAccounts, getTodayAccountConfigInfo } from '@/services/api/account'
  4. import { defineStore } from '../store'
  5. import { useEnumStore } from './enum'
  6. import { useLoginStore } from './login'
  7. import { useUserStore } from './user'
  8. import { usePositionStore } from './position'
  9. import eventBus from '@/services/bus'
  10. /**
  11. * 账号存储对象
  12. * @returns
  13. */
  14. export const useAccountStore = defineStore(() => {
  15. const enumStore = useEnumStore()
  16. const loginStore = useLoginStore()
  17. const userStore = useUserStore()
  18. const positionStore = usePositionStore()
  19. const state = reactive<{
  20. loading: boolean;
  21. accountList: Model.TaAccountsRsp[];
  22. currentAccountId: number;
  23. currentAccountConfig: Model.TodayAccountConfigInfoRsp;
  24. }>({
  25. loading: false,
  26. accountList: [],
  27. currentAccountId: 0,
  28. currentAccountConfig: {
  29. todayAccountMargins: [],
  30. todayAccountTradeRules: [],
  31. todayAccountTradefees: []
  32. }
  33. })
  34. // 资金账户计算列表
  35. const accountComputedList = computed(() => {
  36. const { riskRatioType } = state.currentAccountConfig
  37. const { addmarginriskratio = 0, notemarginriskratio = 0, cutriskratio = 0 } = riskRatioType ?? {}
  38. const result: (Model.TaAccountsRsp & {
  39. freezeMargin: number; // 冻结资金
  40. avaiableBalance: number; // 可用资金
  41. netvalue: number; // 净值
  42. profitLoss: number; // 浮动盈亏
  43. hazardValue: number; // 风险净值
  44. hazardRatio: number; // 风险率
  45. liquidationRate: number; // 斩仓率
  46. hazardRatioColor: string; // 风险率颜色
  47. fractionDigits: number; // 币种小数位
  48. })[] = []
  49. state.accountList.forEach((item) => {
  50. // 账号持仓列表
  51. const positionList = positionStore.positionComputedList.filter((e) => e.accountid === item.accountid)
  52. // 计算浮动盈亏
  53. const profitLoss = positionList.reduce((pre, cur) => cur.tradeproperty === 1 ? pre += cur.profitLoss : pre, 0)
  54. // 计算市值(所有权)
  55. const marketValue = positionList.reduce((pre, cur) => cur.tradeproperty === 2 ? pre += cur.marketValue : pre, 0)
  56. // 计算权益/净值
  57. // 根据系统参数“307 账户净值是否减冻结资金 - 0:不减 1:减“
  58. // 0.净值=期末余额+市值+浮动盈亏(收益权)
  59. // 1.净值=期末余额+市值+浮动盈亏(收益权)-其他冻结-出金冻结
  60. const param307 = userStore.getSystemParamValue('307')
  61. const free = param307 === '1' ? item.otherfreezemargin + item.outamountfreeze : 0 // 冻结资金
  62. const netvalue = item.currentbalance + profitLoss + marketValue - free
  63. // 计算冻结资金 = 冻结+其它冻结+手续费冻结+出金冻结
  64. const freezeMargin = item.freezemargin + item.otherfreezemargin + item.freezecharge + item.outamountfreeze
  65. // 计算可用资金
  66. let avaiableBalance = 0
  67. // *系统参数”113“(当日浮动盈利是否可用) 0:不可用 1:可用
  68. const param113 = userStore.getSystemParamValue('113')
  69. if (profitLoss < 0 || param113 === '1') {
  70. // 账户总浮动盈亏为负:= 期末余额+总浮动盈亏-占用-冻结资金
  71. avaiableBalance = item.currentbalance + profitLoss - item.usedmargin - freezeMargin
  72. } else {
  73. // 账户总浮动盈亏为正 且 113 = 0 :=期末余额-占用-冻结资金
  74. avaiableBalance = item.currentbalance - item.usedmargin - freezeMargin
  75. }
  76. // 计算风险净值 = 期末余额 + 浮动盈亏(收益权) - 其他冻结 - 出金冻结
  77. let hazardValue = item.currentbalance + profitLoss - item.otherfreezemargin - item.outamountfreeze
  78. // 根据系统参数“087 风险净值是否加上市值 - 0:不加 1:加“
  79. const param087 = userStore.getSystemParamValue('087')
  80. if (param087 === '1') {
  81. // 风险净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权) - 其他冻结 - 出金冻结
  82. hazardValue += marketValue
  83. }
  84. // 计算风险率
  85. let hazardRatio = 0
  86. if (hazardValue < 0 || (hazardValue === 0 && item.usedmargin > 0)) {
  87. hazardRatio = 100
  88. }
  89. if (hazardValue > 0 && item.usedmargin > 0) {
  90. // 根据系统参数“132 风险率计算公式”
  91. const param132 = userStore.getSystemParamValue('132')
  92. if (param132 === '1') {
  93. // 风险率 = 占用 / 风险净值
  94. hazardRatio = item.usedmargin / hazardValue
  95. } else {
  96. // 风险率 = (占用 - 授信金额) / (风险净值 - 授信金额)
  97. hazardRatio = (item.usedmargin - item.mortgagecredit) / (hazardValue - item.mortgagecredit)
  98. }
  99. }
  100. // 风险率颜色
  101. let hazardRatioColor = ''
  102. if (hazardRatio < notemarginriskratio) {
  103. hazardRatioColor = 'g-risk-green'
  104. }
  105. if (hazardRatio >= notemarginriskratio && hazardRatio < addmarginriskratio) {
  106. hazardRatioColor = 'g-risk-orange'
  107. }
  108. if (hazardRatio >= addmarginriskratio && hazardRatio < cutriskratio) {
  109. hazardRatioColor = 'g-risk-yellow'
  110. }
  111. if (hazardRatio >= cutriskratio && cutriskratio > 0) {
  112. hazardRatioColor = 'g-risk-red'
  113. }
  114. // 计算斩仓率 任务 #5808
  115. const liquidationRate = cutriskratio ? hazardRatio / cutriskratio : 0
  116. // 币种小数位
  117. const currency = enumStore.getEnumTypeInfo('currency', item.currencyid)
  118. const fractionDigits = currency ? Number(currency.param1) : 2
  119. result.push({
  120. ...item,
  121. freezeMargin,
  122. avaiableBalance,
  123. netvalue,
  124. profitLoss,
  125. hazardValue,
  126. hazardRatio,
  127. hazardRatioColor,
  128. liquidationRate,
  129. fractionDigits
  130. })
  131. })
  132. return result
  133. })
  134. // 当前资金账户信息
  135. const currentAccount = computed(() => {
  136. return {
  137. ...accountComputedList.value.find((e) => e.accountid === state.currentAccountId)
  138. }
  139. })
  140. const filterAccountsByCurrencyId = (...currencyIds: number[]) => {
  141. return accountComputedList.value.filter((e) => currencyIds.includes(e.currencyid))
  142. }
  143. const getAccountItem = (prop: Partial<Model.TaAccountsRsp>) => {
  144. return accountComputedList.value.find(item => isMatch(item, prop))
  145. }
  146. // 获取资金账户列表
  147. const getAccountList = async () => {
  148. try {
  149. state.loading = true
  150. await queryTaAccounts({
  151. data: {
  152. loginID: loginStore.loginId
  153. }
  154. }).then((res) => {
  155. state.accountList = res.data
  156. // 查找当前选中的资金账户
  157. if (!res.data.every((e) => e.accountid === state.currentAccountId)) {
  158. state.currentAccountId = res.data[0]?.accountid ?? 0
  159. }
  160. })
  161. // 任务 #5511
  162. await getTodayAccountConfigInfo().then((res) => {
  163. state.currentAccountConfig = res.data
  164. })
  165. } finally {
  166. state.loading = false
  167. }
  168. }
  169. // 获取账户商品配置
  170. // const getAccountGoodsConfig = (goodsId: number) => {
  171. // const config = state.currentAccountConfig?.todayAccountMargins.find((item, index, self) => {
  172. // // 优先返回账户的商品配置
  173. // if (item.accountid === state.currentAccountId && item.goodsid === goodsId) {
  174. // return true
  175. // }
  176. // // 返回通用的商品配置
  177. // if (!self.some((e) => e.accountid === state.currentAccountId) && item.goodsid === goodsId) {
  178. // return true
  179. // }
  180. // return false
  181. // })
  182. // if (config) {
  183. // const wordArray = CryptoJS.enc.Base64.parse(config.infocontent) // 解析base64
  184. // const uint8Array = wordArrayToUint8Array(wordArray)
  185. // return decodeProto<Proto.MarginInfoStruct>('MarginInfoStruct', uint8Array) // proto数据解析
  186. // }
  187. // return Promise.reject('商品配置不存在')
  188. // }
  189. // 接收资金变动通知
  190. const moneyChangedNotify = eventBus.$on('MoneyChangedNotify', () => getAccountList())
  191. return {
  192. ...toRefs(state),
  193. accountComputedList,
  194. currentAccount,
  195. moneyChangedNotify,
  196. getAccountList,
  197. getAccountItem,
  198. filterAccountsByCurrencyId
  199. }
  200. })