account.ts 8.6 KB

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