Browse Source

更新三角逻辑

flyzto 6 months ago
parent
commit
0b949c93fc

+ 2 - 0
server/init.js

@@ -7,6 +7,8 @@ const Logs = require('./libs/logs');
     innerDefaultAmount: 10000,
     minProfitAmount: 0,
     innerRebateRatio: 0,
+    obRebateRatio: 0,
+    hgRebateRatio: 0,
     runWorkerEnabled: false,
   })
   .then(() => {

+ 40 - 9
server/models/GamesPs.js

@@ -290,27 +290,47 @@ const fetchGamesRelation = async (mk='') => {
       const now = Date.now();
       const gamesRelation = res.data.data?.filter(item => {
         const timestamp = new Date(item.timestamp).getTime();
+        item.timestamp = timestamp;
         return timestamp > now;
       }).map(item => {
         const {
-          id, mk,
+          id, mk, league_name,
           event_id: ps_event_id,
           league_id: ps_league_id,
+          team_home_name: ps_team_home_name,
+          team_away_name: ps_team_away_name,
           ob_event_id, ob_league_id,
+          ob_team_home_name,
+          ob_team_away_name,
           hg_event_id, hg_league_id,
+          hg_team_home_name,
+          hg_team_away_name,
+          timestamp,
         } = item;
         const rel = {
           ps: {
             eventId: +ps_event_id,
-            leagueId: +ps_league_id
+            leagueId: +ps_league_id,
+            leagueName: league_name,
+            teamHomeName: ps_team_home_name,
+            teamAwayName: ps_team_away_name,
+            timestamp
           },
           ob: ob_event_id ? {
             eventId: +ob_event_id,
-            leagueId: +ob_league_id
+            leagueId: +ob_league_id,
+            leagueName: league_name,
+            teamHomeName: ob_team_home_name,
+            teamAwayName: ob_team_away_name,
+            timestamp
           } : null,
           hg: hg_event_id ? {
             eventId: +hg_event_id,
-            leagueId: +hg_league_id
+            leagueId: +hg_league_id,
+            leagueName: league_name,
+            teamHomeName: hg_team_home_name,
+            teamAwayName: hg_team_away_name,
+            timestamp
           } : null
         };
         return { id, mk, rel };
@@ -323,7 +343,7 @@ const fetchGamesRelation = async (mk='') => {
 
 const getGamesRelation = ({ mk, listEvents }) => {
   const relations = Object.values(GAMES.Relations).filter(item => {
-    if (!mk) {
+    if (typeof(mk) == 'undefined') {
       return true;
     }
     return item.mk == mk;
@@ -333,11 +353,12 @@ const getGamesRelation = ({ mk, listEvents }) => {
   }
   return relations.map(item => {
     const { rel, ...relationInfo } = item;
-    Object.keys(rel).forEach(platform => {
-      const { events, evtime, sptime, special, ...gameInfo } = rel[platform];
-      rel[platform] = gameInfo;
+    const tempRel = { ...rel };
+    Object.keys(tempRel).forEach(platform => {
+      const { events, evtime, sptime, special, ...gameInfo } = tempRel[platform];
+      tempRel[platform] = gameInfo;
     });
-    return { ...relationInfo, rel };
+    return { ...relationInfo, rel: tempRel };
   });
 }
 
@@ -349,10 +370,16 @@ const updateGamesRelation = () => {
   .then(res => {
     const gamesRelation = res.flat();
 
+    const updateCount = {
+      add: 0,
+      delete: 0
+    };
+
     gamesRelation.forEach(item => {
       const { id } = item;
       if (!GAMES.Relations[id]) {
         GAMES.Relations[id] = item;
+        updateCount.add ++;
       }
     });
 
@@ -361,9 +388,12 @@ const updateGamesRelation = () => {
     Object.keys(GAMES.Relations).forEach(id => {
       if (!relations.has(+id)) {
         delete GAMES.Relations[id];
+        updateCount.delete ++;
       }
     });
 
+    Logs.out('updateGamesRelation', updateCount);
+
   })
   .catch(err => {
     Logs.out('updateGamesRelation', err.message);
@@ -403,6 +433,7 @@ const updateGamesResult = (result) => {
  */
 const setSolutions = (solutions) => {
   //TODO: 保存解决方案
+  Logs.out('setSolutions', solutions);
 }
 
 /**

+ 10 - 0
server/models/Setting.js

@@ -21,6 +21,16 @@ const systemSettingSchema = new Schema({
     required: true,
     default: 0
   },
+  obRebateRatio: {
+    type: Number,
+    required: true,
+    default: 0
+  },
+  hgRebateRatio: {
+    type: Number,
+    required: true,
+    default: 0
+  },
   runWorkerEnabled: {
     type: Boolean,
     required: true,

+ 24 - 14
server/triangle/eventsMatch.js

@@ -13,6 +13,8 @@ const SETTING = {
   innerDefaultAmount: 10000,
   minProfitAmount: 0,
   innerRebateRatio: 0,
+  obRebateRatio: 0,
+  hgRebateRatio: 0,
   runWorkerEnabled: false
 }
 
@@ -126,20 +128,23 @@ const extractOdds = ({ evtime, events, sptime, special }) => {
 const eventMatch = () => {
   getGamesRelation()
   .then(relations => {
-    if (!relations?.length) {
-      return;
-    }
+    // Logs.out('eventMatch', relations);
+    // if (!relations?.length) {
+    //   return;
+    // }
 
-    const nowTime = Date.now();
-    relations = relations.filter(relaiton => {
-      const expire = Object.values(relaiton.rel).find(event => event.timestamp <= nowTime);
-      if (expire) {
-        return false;
-      }
-      return true;
-    });
+    // const nowTime = Date.now();
+    // relations = relations.filter(relaiton => {
+    //   const expire = Object.values(relaiton.rel).find(event => event.timestamp <= nowTime);
+    //   if (expire) {
+    //     return false;
+    //   }
+    //   return true;
+    // });
 
-    const relationLength = relations.length;
+    Logs.out('eventMatch relations', relations);
+
+    const relationLength = relations?.length;
     if (!relationLength) {
       if (GLOBAL_DATA.relationLength) {
         GLOBAL_DATA.relationLength = 0;
@@ -158,7 +163,7 @@ const eventMatch = () => {
         if (!events && !special) {
           return;
         }
-        if (!eventsMap.info) {
+        if (platform == 'ps') {
           eventsMap.info = { leagueName, teamHomeName, teamAwayName, id, timestamp };
         }
         const odds = extractOdds({ evtime, events, sptime, special });
@@ -171,9 +176,14 @@ const eventMatch = () => {
       });
       eventsMap.odds = oddsMap;
       return eventsMap;
-    });
+    })
+    .filter(item => item.info);
+
+    // Logs.out('eventMatch passableEvents', passableEvents);
 
     const solutions = eventsCombination(passableEvents, SETTING);
+
+    // Logs.out('eventMatch solutions', solutions);
     setSolutions(solutions);
   })
   .finally(() => {

+ 7 - 7
server/triangle/iorKeys.js

@@ -1,15 +1,15 @@
 module.exports = {
   A: [
-    ['ior_rh_05', 'ior_rac_025', 'ior_mn', 'la_wh_wa'],
-    ['ior_rc_05', 'ior_rah_025', 'ior_mn', 'la_wh_wa'],
+    ['ior_mh', 'ior_rac_025', 'ior_mn', 'la_wh_wa'],
+    ['ior_mc', 'ior_rah_025', 'ior_mn', 'la_wh_wa'],
 
-    ['ior_rh_05', 'ior_rc_0', 'ior_mn', 'la_dr_wa'],
-    ['ior_rc_05', 'ior_rh_0', 'ior_mn', 'la_dr_wa'],
+    ['ior_mh', 'ior_rc_0', 'ior_mn', 'la_dr_wa'],
+    ['ior_mc', 'ior_rh_0', 'ior_mn', 'la_dr_wa'],
 
-    ['ior_rh_05', 'ior_rc_025', 'ior_mn', 'la_lh_wa'],
-    ['ior_rc_05', 'ior_rh_025', 'ior_mn', 'la_lh_wa'],
+    ['ior_mh', 'ior_rc_025', 'ior_mn', 'la_lh_wa'],
+    ['ior_mc', 'ior_rh_025', 'ior_mn', 'la_lh_wa'],
 
-    ['ior_rh_05', 'ior_rc_05', 'ior_mn', 'la_la_wa'],
+    ['ior_mh', 'ior_mc', 'ior_mn', 'la_la_wa'],
 
     ['ior_rh_025', 'ior_rc_0', 'ior_mn', 'lh_dr_wa'],
     ['ior_rc_025', 'ior_rh_0', 'ior_mn', 'lh_dr_wa'],

+ 13 - 13
server/triangle/totalProfitCalc.js

@@ -119,14 +119,14 @@ const HandicapCalc = function (data) {
 }
 
 const calcExternalHandicap = (data) => {
-  const { gold_side_inner: g, odds_side_a: a, odds_side_b: b, odds_side_m: c, inner_index: i, cross_type: t, win_target: w, loss_out_1 } = data;
+  const { gold_side_inner: g, odds_side_a: a, odds_side_b: b, odds_side_c: c, inner_index: i, cross_type: t, win_target: w, loss_out_1 } = data;
   const l = loss_out_1 ?? 0;
   const calc = new HandicapCalc({ i, g, a, b, c, w, l });
   const { x, y, z } = calc?.[t]() ?? {};
   return {
     gold_side_a: fixFloat(x),
     gold_side_b: fixFloat(y),
-    gold_side_m: fixFloat(z),
+    gold_side_c: fixFloat(z),
     inner_index: i,
   }
 
@@ -137,30 +137,30 @@ const calcGoldsWithWinTarget = (data) => {
   const {
     gold_side_a: goldA1,
     gold_side_b: goldB1,
-    gold_side_m: goldM1,
+    gold_side_c: goldC1,
     inner_index: inner_index_1
   } = calcExternalHandicap({ ...sol1, gold_side_inner, win_target });
 
   let loss_out_1 = 0, win_inner_1 = 0;
   switch (inner_index_1) {
     case 0:
-      loss_out_1 = goldB1 + goldM1;
+      loss_out_1 = goldB1 + goldC1;
       win_inner_1 = gold_side_inner * (sol1.odds_side_a + 1);
       break;
     case 1:
-      loss_out_1 = goldA1 + goldM1;
+      loss_out_1 = goldA1 + goldC1;
       win_inner_1 = gold_side_inner * (sol1.odds_side_b + 1);
       break;
     case 2:
       loss_out_1 = goldA1 + goldB1;
-      win_inner_1 = gold_side_inner * (sol1.odds_side_m + 1)
+      win_inner_1 = gold_side_inner * (sol1.odds_side_c + 1)
       break;
   }
 
   const {
     gold_side_a: goldA2,
     gold_side_b: goldB2,
-    gold_side_m: goldM2,
+    gold_side_c: goldC2,
     inner_index: inner_index_2
   } = calcExternalHandicap({ ...sol2, gold_side_inner, win_target, loss_out_1 });
 
@@ -168,18 +168,18 @@ const calcGoldsWithWinTarget = (data) => {
   switch (inner_index_2) {
     case 0:
       inner_base_key = 'goldA2';
-      loss_out_2 = gold_side_inner +goldB2 + goldM2 + loss_out_1;
+      loss_out_2 = gold_side_inner +goldB2 + goldC2 + loss_out_1;
       win_inner_2 = win_inner_1 * (sol2.odds_side_a + 1);
       break;
     case 1:
       inner_base_key = 'goldB2';
-      loss_out_2 = gold_side_inner + goldA2 + goldM2 + loss_out_1;
+      loss_out_2 = gold_side_inner + goldA2 + goldC2 + loss_out_1;
       win_inner_2 = win_inner_1 * (sol2.odds_side_b + 1);
       break;
     case 2:
-      inner_base_key = 'goldM2';
+      inner_base_key = 'goldC2';
       loss_out_2 = gold_side_inner + goldA2 + goldB2 + loss_out_1;
-      win_inner_2 = win_inner_1 * (sol2.odds_side_m + 1);
+      win_inner_2 = win_inner_1 * (sol2.odds_side_c + 1);
       break;
   }
 
@@ -188,10 +188,10 @@ const calcGoldsWithWinTarget = (data) => {
   const result = {
     goldA1,
     goldB1,
-    goldM1,
+    goldC1,
     goldA2,
     goldB2,
-    goldM2,
+    goldC2,
     win_inner,
     inner_index_1,
     inner_index_2,

+ 98 - 46
server/triangle/trangleCalc.js

@@ -5,15 +5,20 @@ const SETTING = {
   innerDefaultAmount: 10000,
   minProfitAmount: 0,
   innerRebateRatio: 0,
+  obRebateRatio: 0,
+  hgRebateRatio: 0,
 }
 
 /**
  * 筛选最优赔率
  */
-function getOptimalSelections(data, combos) {
+function getOptimalSelections(odds, rules) {
   const results = [];
+  const { obRebateRatio, hgRebateRatio } = SETTING;
+  const obRebate = 1 + obRebateRatio / 100;
+  const hgRebate = 1 + hgRebateRatio / 100;
 
-  combos.forEach((rule, index) => {
+  rules.forEach((rule, index) => {
     let validOptions = [];
 
     for (let i = 0; i < 3; i++) {
@@ -22,7 +27,7 @@ function getOptimalSelections(data, combos) {
       let isValid = true;
       for (let j = 0; j < 3; j++) {
         const key = rule[j];
-        const item = data[key];
+        const item = odds[key];
 
         if (!item) {
           isValid = false;
@@ -46,7 +51,7 @@ function getOptimalSelections(data, combos) {
             isValid = false;
             break;
           }
-          const best = candidates.reduce((a, b) => item[a] > item[b] ? a : b);
+          const best = candidates.reduce((a, b) => item[a]*obRebate > item[b]*hgRebate ? a : b);
           selection.push({
             k: key,
             p: best,
@@ -92,13 +97,13 @@ const triangleProfitCalc = (goldsInfo, oddsOption) => {
   const {
     gold_side_a: x,
     gold_side_b: y,
-    gold_side_m: z,
+    gold_side_c: z,
     odds_side_a: a,
     odds_side_b: b,
-    odds_side_m: c
+    odds_side_c: c
   } = goldsInfo;
 
-  const { crossType, innerIndex } = oddsOption;
+  const { crossType, innerIndex, rebateA: A = 0, rebateB: B = 0, rebateC: C = 0 } = oddsOption;
   /**
    * crossType:
    *  la: 全输
@@ -120,67 +125,67 @@ const triangleProfitCalc = (goldsInfo, oddsOption) => {
     inner_rebate = z * innerRebateRatio;
   }
 
-  let win_side_a = 0, win_side_b = 0, win_side_m = 0;
-  win_side_a = a * x - y - z;
-  win_side_b = b * y - x - z;
+  let win_side_a = 0, win_side_b = 0, win_side_c = 0;
+  win_side_a = a*x - y - z + a*A*x + B*y + C*z;
+  win_side_b = b*y - x - z + b*B*y + A*x + C*z;
 
   switch (crossType) {
     case 'la_wh_wa': // 全输 半赢 全赢
-      win_side_m = c*z - x + b*y/2;
+      win_side_c = c*z - x + b*y/2 + c*C*z + A*x + b*B*y/2;
       break;
     case 'la_dr_wa': // 全输 和局 全赢
-      win_side_m = c*z - x;
+      win_side_c = c*z - x + c*C*z + A*x;
       break;
     case 'la_lh_wa': // 全输 半输 全赢
-      win_side_m = c*z - x - y/2;
+      win_side_c = c*z - x - y/2 + c*C*z + A*x + B*y/2;
       break;
     case 'lh_dr_wa': // 半输 和局 全赢
-      win_side_m = c*z - x/2;
+      win_side_c = c*z - x/2 + c*C*z + A*x/2;
       break;
     case 'lh_lh_wa': // 半输 半输 全赢
-      win_side_m = c*z - x/2 - y/2;
+      win_side_c = c*z - x/2 - y/2 + c*C*z + A*x/2 + B*y/2;
       break;
     case 'la_la_wa': // 全输 全输 全赢
-      win_side_m = c*z - x - y;
+      win_side_c = c*z - x - y + c*C*z + A*x + B*y;
       break;
   }
 
   win_side_a = fixFloat(win_side_a + inner_rebate);
   win_side_b = fixFloat(win_side_b + inner_rebate);
-  win_side_m = fixFloat(win_side_m + inner_rebate);
-  const win_average = fixFloat((win_side_a + win_side_b + win_side_m) / 3);
+  win_side_c = fixFloat(win_side_c + inner_rebate);
+  const win_average = fixFloat((win_side_a + win_side_b + win_side_c) / 3);
 
-  return { win_side_a, win_side_b, win_side_m, win_average }
+  return { win_side_a, win_side_b, win_side_c, win_average }
 }
 
 const triangleGoldCalc = (oddsInfo, oddsOption) => {
   const { innerDefaultAmount } = SETTING;
-  const { odds_side_a: a, odds_side_b: b, odds_side_m: c } = oddsInfo;
+  const { odds_side_a: a, odds_side_b: b, odds_side_c: c } = oddsInfo;
   if (!a || !b || !c) {
     return;
   }
-  const { crossType, innerIndex } = oddsOption;
+  const { crossType, innerIndex, rebateA: A = 0, rebateB: B = 0, rebateC: C = 0 } = oddsOption;
   let x = innerDefaultAmount;
-  let y = (a + 1) * x / (b + 1);
+  let y = (a + a*A + 1 - A) * x / (b + b*B + 1 - B);
   let z;
   switch (crossType) {
     case 'la_wh_wa': // 全输 半赢 全赢
-      z = b * y / 2 / (c + 1);
+      z = (b + b*B) * y / 2 / (c + c*C + 1 - C);
       break;
     case 'la_dr_wa': // 全输 和局 全赢
-      z = b * y / (c + 1);
+      z = (b + b*B) * y / (c + c*C + 1 - C);
       break;
     case 'la_lh_wa': // 全输 半输 全赢
-      z = (2 * b + 1) * y / 2 / (c + 1);
+      z = (2*b + 2*b*B + 1 - B) * y / 2 / (c + c*C + 1 - C);
       break;
     case 'lh_dr_wa': // 半输 和局 全赢
-      z = (b * y - x / 2) / (c + 1);
+      z = ((b + b*B) * y - (1 - A) * x / 2) / (c + c*C + 1 - C);
       break;
     case 'lh_lh_wa': // 半输 半输 全赢
-      z = (b * y + y / 2 - x / 2) / (c + 1);
+      z = ((2*b + 2*b*B + 1 - B) * y / 2 + (1 - A) * x / 2) / (c + c*C + 1 - C);
       break;
     case 'la_la_wa': // 全输 全输 全赢
-      z = (b + 1) * y / (c + 1);
+      z = (b + b*B + 1 - B) * y / (c + c*C + 1 - C);
       break;
     default:
       z = 0;
@@ -202,10 +207,10 @@ const triangleGoldCalc = (oddsInfo, oddsOption) => {
   return {
     gold_side_a: x,
     gold_side_b: fixFloat(y),
-    gold_side_m: fixFloat(z),
+    gold_side_c: fixFloat(z),
     odds_side_a: a,
     odds_side_b: b,
-    odds_side_m: c,
+    odds_side_c: c,
   };
 
 }
@@ -218,12 +223,12 @@ const eventSolutions = (oddsInfo, oddsOption) => {
   }
   const profitInfo = triangleProfitCalc(goldsInfo, oddsOption);
 
-  const { odds_side_a, odds_side_b, odds_side_m } = goldsInfo;
+  const { odds_side_a, odds_side_b, odds_side_c } = goldsInfo;
   const { win_average } = profitInfo;
   return {
     odds_side_a,
     odds_side_b,
-    odds_side_m,
+    odds_side_c,
     win_average,
     cross_type: oddsOption.crossType,
     inner_index: oddsOption.innerIndex,
@@ -231,6 +236,35 @@ const eventSolutions = (oddsInfo, oddsOption) => {
   }
 }
 
+/**
+ * 将数组中的指定索引的元素移动到最前面
+*/
+const moveToFront = (arr, index) => {
+  if (index < 0 || index >= arr.length) return arr; // index 越界处理
+  const item = arr.splice(index, 1)[0]; // 删除该项并获取
+  arr.unshift(item); // 插入到最前面
+  return arr;
+}
+
+/**
+ * 添加返佣
+ */
+const attachRebate = (ior) => {
+  const { innerRebateRatio, obRebateRatio, hgRebateRatio } = SETTING;
+  const { p } = ior;
+  let rebate = 0;
+  if (p == 'ps') {
+    rebate = innerRebateRatio;
+  }
+  else if (p == 'ob') {
+    rebate = obRebateRatio;
+  }
+  else if (p == 'hg') {
+    rebate = hgRebateRatio;
+  }
+  return { ...ior, r: rebate };
+}
+
 const eventsCombination = (passableEvents, setting) => {
 
   Object.keys(setting).forEach(key => {
@@ -240,42 +274,60 @@ const eventsCombination = (passableEvents, setting) => {
     }
   });
 
-  const solutions = [];
+  const solutions = {};
   passableEvents.forEach(events => {
     const { odds, info } = events;
-    Object.keys(IOR_KEYS_MAP).forEach(group => {
-      const rules = IOR_KEYS_MAP[group];
+    Object.keys(IOR_KEYS_MAP).forEach(iorGroup => {
+      const rules = IOR_KEYS_MAP[iorGroup];
       const optimalSelections = getOptimalSelections(odds, rules);
+
       optimalSelections.forEach(selection => {
         const { rule, iors, index } = selection;
         const [, , , crossType] = rule;
-
-        const oddsSideA = iors[0];
-        const oddsSideB = iors[1];
-        const oddsSideM = iors[2];
+        const oddsSideA = attachRebate(iors[0]);
+        const oddsSideB = attachRebate(iors[1]);
+        const oddsSideC = attachRebate(iors[2]);
         const innerIndex = iors.findIndex(item => item.p == 'ps');
-        if (!oddsSideA || !oddsSideB || !oddsSideM) {
+        if (!oddsSideA || !oddsSideB || !oddsSideC) {
           return;
         }
-        const cpr = [ oddsSideA, oddsSideB, oddsSideM ];
+        const cpr = [ oddsSideA, oddsSideB, oddsSideC ];
         const oddsInfo = {
           odds_side_a: fixFloat(oddsSideA.v - 1),
           odds_side_b: fixFloat(oddsSideB.v - 1),
-          odds_side_m: fixFloat(oddsSideM.v - 1)
+          odds_side_c: fixFloat(oddsSideC.v - 1),
+        };
+        const oddsOption = {
+          crossType, innerIndex,
+          rebateA: parseFloat((oddsSideA.r / 100).toFixed(4)),
+          rebateB: parseFloat((oddsSideB.r / 100).toFixed(4)),
+          rebateC: parseFloat((oddsSideC.r / 100).toFixed(4)),
         };
-        const oddsOption = { crossType, innerIndex };
         const sol = eventSolutions(oddsInfo, oddsOption);
         if (sol?.win_average > SETTING.minProfitAmount) {
           const id = info.id;
-          const keys = cpr.map(item => `${item.k}`).join('_');
+          const sortedCpr = moveToFront([...cpr], innerIndex);
+          const crpGroup = `${id}_${sortedCpr[0].k}`;
+          const keys = sortedCpr.map(item => `${item.k}`).join('_');
           const sid = `${id}_${keys}`;
           const timestamp = Date.now();
-          solutions.push({sid, sol, cpr, info, rule: `${group}:${index}`, timestamp});
+          if (!solutions[crpGroup]) {
+            solutions[crpGroup] = [];
+          }
+          solutions[crpGroup].push({sid, sol, cpr, info, rule: `${iorGroup}:${index}`, timestamp});
         }
       });
     });
   });
-  return solutions;
+  return Object.values(solutions).map(item => {
+    return item.sort((a, b) => {
+      return b.sol.win_average - a.sol.win_average;
+    })
+    .slice(0, 2);
+  })
+  .sort((a, b) => {
+    return b[0].sol.win_average - a[0].sol.win_average;
+  });
 }
 
 module.exports = { eventsCombination };

+ 32 - 4
web/apps/web-antd/src/views/system/parameter/index.vue

@@ -8,6 +8,8 @@ const initialFormState = {
   innerDefaultAmount: 10000,
   minProfitAmount: 0,
   innerRebateRatio: 0,
+  obRebateRatio: 0,
+  hgRebateRatio: 0,
   runWorkerEnabled: false
 };
 
@@ -39,8 +41,8 @@ const getSetting = async () => {
 const saveSetting = async () => {
   try {
     await requestClient.post('/system/update_setting', formState);
-    isFormChanged.value = false;
     message.success('保存成功');
+    syncSetting();
   }
   catch (error) {
     console.error('Failed to save setting:', error);
@@ -94,21 +96,47 @@ onUnmounted(() => {
       >
         <InputNumber
           v-model:value="formState.minProfitAmount"
-          :min="-10000"
+          :min="-99999"
           :step="1"
           style="width: 200px"
         />
       </Form.Item>
 
       <Form.Item
-        label="内盘返点比例"
+        label="内盘返点比例(%)"
         name="innerRebateRatio"
       >
         <InputNumber
           v-model:value="formState.innerRebateRatio"
           :min="0"
           :max="100"
-          :step="1"
+          :step="0.1"
+          style="width: 200px"
+        />
+      </Form.Item>
+
+      <Form.Item
+        label="OB返点比例(%)"
+        name="obRebateRatio"
+      >
+        <InputNumber
+          v-model:value="formState.obRebateRatio"
+          :min="0"
+          :max="100"
+          :step="0.1"
+          style="width: 200px"
+        />
+      </Form.Item>
+
+      <Form.Item
+        label="HG返点比例(%)"
+        name="hgRebateRatio"
+      >
+        <InputNumber
+          v-model:value="formState.hgRebateRatio"
+          :min="0"
+          :max="100"
+          :step="0.1"
           style="width: 200px"
         />
       </Form.Item>