index.ts 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import { reactive, ref, computed } from 'vue';
  2. import { queryErmcpTradePosition } from '@/services/go/ermcp/futures';
  3. import { QueryErmcpTradePositionRsp } from '@/services/go/ermcp/futures/interface';
  4. import { getQuoteDayInfoByCode } from "@/services/bus/goods";
  5. import { BuyOrSell } from '@/common/constants/enumCommon';
  6. import { getTaAccounts } from '@/services/go/TaAccount';
  7. import { Taaccount } from "@/services/go/TaAccount/interface";
  8. import { geLoginID_number } from '@/services/bus/login';
  9. import { Systemparam } from '@/services/go/useInfo/interface';
  10. import { getSelectedAccountId, setSelectedAccount } from '@/services/bus/account'; // 为了兼容以前代码,待优化后期废除
  11. import { TradeAccount, TradePosition } from './interface'
  12. import APP from '@/services';
  13. // 加载状态
  14. const loading = ref<boolean>(false);
  15. // 资金账户列表
  16. const tradeAccountList: TradeAccount[] = reactive([]);
  17. // 当前账户期货持仓列表
  18. const tradePositionList: TradePosition[] = reactive([]);
  19. // 当前资金账户信息
  20. const tradeAccount = ref<TradeAccount>();
  21. /**
  22. * 资金账户
  23. */
  24. export function useTradeAccount() {
  25. // 获取资金账户列表
  26. const getTradeAccountList = () => {
  27. if (!loading.value) {
  28. tradeAccountList.length = 0;
  29. loading.value = true;
  30. // 登录ID
  31. const loginID = Number(geLoginID_number());
  32. getTaAccounts({ loginID }).then(async (res) => {
  33. for (let i = 0; i < res.length; i++) {
  34. const account = res[i];
  35. const positionList: TradePosition[] = [];
  36. // 获取账户下的期货持仓列表
  37. await queryErmcpTradePosition({ accountID: account.accountid }).then((res) => {
  38. res.forEach((item) => {
  39. positionList.push({
  40. ...item,
  41. ...calcPositionValue(item),
  42. })
  43. })
  44. })
  45. tradeAccountList.push({
  46. positionList,
  47. ...account,
  48. ...calcCapitalValue(account, positionList),
  49. })
  50. }
  51. tradeAccountChange(getSelectedAccountId());
  52. loading.value = false;
  53. })
  54. }
  55. }
  56. // 切换资金账户
  57. const tradeAccountChange = (accountId: number) => {
  58. const account = tradeAccountList.find((account) => account.accountid === accountId);
  59. if (account) {
  60. tradePositionList.length = 0;
  61. tradeAccount.value = account;
  62. tradePositionList.push(...account.positionList);
  63. setSelectedAccount(account); // 为了兼容以前代码,待优化后期废除
  64. }
  65. }
  66. // 期货账户列表
  67. const futuresAccountList = computed(() => tradeAccountList.filter((account) => account.taaccounttype === 1));
  68. return {
  69. loading,
  70. tradeAccountList,
  71. tradePositionList,
  72. tradeAccount,
  73. futuresAccountList,
  74. getTradeAccountList,
  75. tradeAccountChange,
  76. }
  77. }
  78. /**
  79. * 计算持仓数据
  80. * @param position
  81. * @returns
  82. */
  83. function calcPositionValue(position: QueryErmcpTradePositionRsp) {
  84. // 获取对应的商品行情
  85. const quote = getQuoteDayInfoByCode(position.goodscode);
  86. // 计算开仓均价
  87. const openAveragePrice = computed(() => {
  88. const { opencost, curpositionqty, agreeunit } = position
  89. // 开仓成本 ÷ 期末头寸 ÷ 合约单位
  90. return opencost / curpositionqty / agreeunit;
  91. })
  92. // 计算持仓均价
  93. const positionAveragePrice = computed(() => {
  94. const { positioncost, curpositionqty, agreeunit } = position
  95. // 持仓成本 ÷ 期末头寸 ÷ 合约单位
  96. return positioncost / curpositionqty / agreeunit;
  97. })
  98. // 计算浮动盈亏 - 对应市场收益权
  99. const positionProfitAndLoss = computed(() => {
  100. const { curpositionqty, agreeunit } = position
  101. if (quote?.last) {
  102. if (position.buyorsell === BuyOrSell.buy) {
  103. // 买方向 = (最新价 - 持仓均价) * 买期末头寸 * 合约单位
  104. return (quote.last - openAveragePrice.value) * curpositionqty * agreeunit
  105. } else {
  106. // 卖方向 = (持仓均价 - 最新价) * 卖期末头寸 * 合约单位
  107. return (positionAveragePrice.value - quote.last) * curpositionqty * agreeunit
  108. }
  109. }
  110. return position.positionpl
  111. })
  112. // 计算市值 - 对应市场所有权
  113. const capitalization = computed(() => {
  114. if (quote?.last) {
  115. // 市值 = 最新价 * 持仓数量 * 合约单位
  116. return quote.last * position.curpositionqty * position.agreeunit
  117. }
  118. return 0
  119. })
  120. // 计算盈亏比例
  121. const positionProfitAndLossRate = computed(() => {
  122. const { opencost } = position
  123. // 持仓盈亏 ÷ 开仓成本
  124. const result = positionProfitAndLoss.value / opencost * 100
  125. if (isNaN(result)) {
  126. return 0
  127. }
  128. return result
  129. })
  130. return {
  131. openAveragePrice,
  132. capitalization,
  133. positionAveragePrice,
  134. positionProfitAndLoss,
  135. positionProfitAndLossRate,
  136. }
  137. }
  138. /**
  139. * 计算资金数据
  140. * @param account
  141. * @param positionList
  142. * @returns
  143. */
  144. function calcCapitalValue(account: Taaccount, positionList: TradePosition[]) {
  145. // 系统参数
  146. const systemParams = <Systemparam[]>APP.get('systemParams');
  147. // 计算总浮动盈亏
  148. const positionProfitAndLoss = computed(() => positionList.reduce((res, item) => res + item.positionProfitAndLoss.value, 0));
  149. // 计算总市值
  150. const marketCap = computed(() => positionList.reduce((res, item) => res + item.capitalization.value, 0));
  151. // 计算可用资金
  152. const availableBalance = computed(() => {
  153. // *系统参数"113"(当日浮动盈利是否可用) 0:不可用 1:可用
  154. const flag = systemParams.find((e) => e.paramcode === '113')?.paramvalue === '1';
  155. const { currentbalance, usedmargin, freezemargin, freezecharge, otherfreezemargin, outamountfreeze } = account;
  156. const freeze = currentbalance - usedmargin - freezemargin - otherfreezemargin - freezecharge - outamountfreeze;
  157. if (positionProfitAndLoss.value < 0 || (positionProfitAndLoss.value >= 0 && flag)) {
  158. // 账户(总浮动盈亏为负) 或(总浮动盈亏为正 且 113 = 1)
  159. // 可用资金 = 总浮动盈亏 + 期末余额 - 占用 - 冻结 - 其它冻结 - 手续费冻结 - 出金冻结
  160. return positionProfitAndLoss.value + freeze;
  161. } else {
  162. // 可用资金 = 期末余额 - 占用 - 冻结 - 其它冻结 - 手续费冻结 - 出金冻结
  163. return freeze;
  164. }
  165. });
  166. // 计算权益/净值
  167. const equity = computed(() => {
  168. // 根据系统参数“307 账户净值是否减冻结资金 - 0:不减 1:减“
  169. const flag = systemParams.find((e) => e.paramcode === '307')?.paramvalue === '1';
  170. const result = account.currentbalance + marketCap.value + positionProfitAndLoss.value;
  171. if (flag) {
  172. const { otherfreezemargin, outamountfreeze } = account;
  173. // 净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权) - 其它冻结 - 出金冻结
  174. return result - otherfreezemargin - outamountfreeze;
  175. } else {
  176. // 净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权)
  177. return result;
  178. }
  179. })
  180. // 计算冻结资金
  181. const freezeAmount = computed(() => {
  182. const { otherfreezemargin, outamountfreeze, freezecharge } = account;
  183. // 冻结资金 = 手续费冻结 + 出金冻结 + 其他冻结保证金
  184. return freezecharge + outamountfreeze + otherfreezemargin;
  185. })
  186. // 计算风险净值
  187. const valueAtRisk = computed(() => {
  188. // 根据系统参数“307 账户净值是否减冻结资金 - 0:不减 1:减“
  189. const flag = systemParams.find((e) => e.paramcode === '087')?.paramvalue === '1';
  190. const { otherfreezemargin, outamountfreeze } = account;
  191. const result = account.currentbalance + positionProfitAndLoss.value - otherfreezemargin - outamountfreeze;
  192. if (flag) {
  193. // 风险净值 = 期末余额 + 市值(所有权) + 浮动盈亏(收益权) - 其他冻结-出金冻结
  194. return result + marketCap.value;
  195. } else {
  196. // 风险净值 = 期末余额 + 浮动盈亏(收益权) - 其他冻结 - 出金冻结
  197. return result;
  198. }
  199. })
  200. // 计算风险率
  201. const hazardRatio = computed(() => {
  202. // 根据系统参数“132 风险率计算公式”:
  203. const flag = systemParams.find((e) => e.paramcode === '132')?.paramvalue === '1';
  204. const { usedmargin, mortgagecredit } = account;
  205. if (flag) {
  206. // 风险率 = 占用 / 风险净值
  207. return usedmargin / valueAtRisk.value;
  208. } else {
  209. // 风险率 = (占用 - 授信金额) / (风险净值 - 授信金额)
  210. return (usedmargin - mortgagecredit) / (valueAtRisk.value - mortgagecredit);
  211. }
  212. })
  213. return {
  214. equity,
  215. positionProfitAndLoss,
  216. availableBalance,
  217. freezeAmount,
  218. hazardRatio,
  219. }
  220. }