DEV Community

BeGoodTool.com
BeGoodTool.com

Posted on

A "maintenance margin ratio" isn't one formula — it's two, and mixing them up gives you the wrong liquidation price

I put together a margin call calculator for leveraged stock positions after realizing I kept doing the same algebra by hand every time a family member asked "so at what price do I get a margin call." Simple enough, I thought — one formula, plug in the numbers. Then I actually tried to support both Taiwan-style brokers and US/EU-style brokers in the same tool, and found out they don't even define "maintenance ratio" the same way. Same underlying risk, two different formulas, and if you solve the wrong one for price you get a number that's confidently wrong.

Two formulas hiding behind one label

Taiwanese, Chinese, and Korean brokers report something usually called "整戶擔保維持率" (overall collateral maintenance ratio): total position value divided by the outstanding loan. A healthy account sits around 166%. US/EU brokers instead report an equity percentage: (value minus debt) divided by value. A healthy account there might be 40%. Both numbers describe the exact same account state — they're just expressed as different ratios, and a 30% equity ratio is not "worse" than a 166% collateral ratio, it's the same leverage described from the other side of the fraction.

The tool branches on that explicitly:

const isAsianMode = computed(() => {
  return ["tw", "cn", "kr"].includes(locale.value);
});

const now_maintenance_ratio = computed(() => {
  if (!now_price.value || !buy_quantity.value || !financing.value) return 0;

  let currentTotalValue = now_price.value * buy_quantity.value;
  let loanAmount = financing.value - maintenance_margin.value;

  let res = 0;
  if (isAsianMode.value) {
    // Total market value / loan amount (e.g. 166%)
    res = (currentTotalValue / loanAmount) * 100;
  } else {
    // (Total market value - loan) / total market value (e.g. 40%)
    // i.e. Equity / Total Value
    let equity = currentTotalValue - loanAmount;
    res = (equity / currentTotalValue) * 100;
  }

  return Math.ceil(res * 100) / 100;
});
Enter fullscreen mode Exit fullscreen mode

Locale isn't just a UI label swap here — it changes which formula actually runs, and the default maintenance ratio the input starts at (130% for the Asian mode, 30% for the Western mode) is set by a watcher on locale for exactly that reason. Type a "30" into the Asian branch by mistake and the tool will treat it as an account already deep past liquidation, because 30% collateral coverage would mean the loan is more than three times the position value.

Solving the same inequality for price, from both directions

The actual point of the tool isn't showing you today's ratio — you can compute that from your brokerage app already. It's rearranging the ratio formula to solve for the price where the ratio crosses the danger line, which is a bit more algebra than most people want to do by hand mid-panic. The source comments actually spell out both derivations, so I'll just show them as written:

const gg_price = computed(() => {
  if (!financing.value || !buy_quantity.value) return 0;

  let loanAmount = financing.value - maintenance_margin.value;
  let ratioDecimal = maintenance_ratio.value / 100;
  let gg = 0;

  if (isAsianMode.value) {
    // Asian derivation: Price * Qty / Loan = 1.3  =>  Price = 1.3 * Loan / Qty
    gg = (loanAmount * ratioDecimal) / buy_quantity.value;
  } else {
    // Western derivation: (Price*Qty - Loan) / (Price*Qty) = 0.3
    // 1 - Loan/(Price*Qty) = 0.3
    // 0.7 = Loan/(Price*Qty)
    // Price = Loan / (0.7 * Qty)
    // General form: Price = Loan / ((1 - Ratio) * Qty)
    gg = loanAmount / ((1 - ratioDecimal) * buy_quantity.value);
  }

  return Math.ceil(gg * 100) / 100;
});
Enter fullscreen mode Exit fullscreen mode

Both branches are the same move — take the maintenance-ratio inequality, substitute Price × Quantity for "current value," and isolate Price — but the Western one needs an extra step because the ratio is defined against value instead of against the loan directly. It's a good reminder that "just solve for x" isn't always symmetric even when the two formulas describe the same thing.

Extra margin reduces the loan, not the equity

There's a modeling decision buried in one line that's easy to read past: loanAmount = financing.value - maintenance_margin.value. When you deposit extra cash after opening the position, the code treats it as paying down the loan balance, not as adding to your equity side of the ledger. Both are mathematically valid ways to represent the same cash injection, but they're not interchangeable inside the ratio formulas above — subtracting it from the loan is what makes the Asian ratio (value / loan) actually go up when you deposit more, since a smaller denominator directly raises the ratio. If it had been added to a separate equity variable instead, the Asian branch's formula would have needed to change shape entirely. Small choice, but it's the one that keeps a single formula valid across "no extra deposit yet" and "already topped up once."

The same subtraction shows up again when solving for how much to deposit to get back to a target ratio (say, restoring to 166% instead of just clearing the 130% floor):

if (isAsianMode.value) {
  // Total / (Loan - Add) = Target  =>  Add = Loan - (Total / Target)
  needValue = loanAmount - currentTotalValue / targetDecimal;
} else {
  // (Total - (Loan - Add)) / Total = Target  =>  Add = Loan - Total * (1 - Target)
  needValue = loanAmount - currentTotalValue * (1 - targetDecimal);
}
Enter fullscreen mode Exit fullscreen mode

Same substitution, just solved for Add instead of Price this time, then floored at 0 with res > 0 ? res : 0 so a position that's already healthy doesn't show a negative "deposit this much" instruction.

Rounding decisions that matter more than they look

Three different roundings show up for three different reasons:

  • The initial equity (self_provided) is rounded up with Math.ceil — if the exact split leaves a fraction of a currency unit, you should never be shown less equity than you actually need to put in.
  • The computed loan amount (financing) is rounded down with Math.floor — same logic from the other side, since equity + loan should never silently exceed the position's actual cost.
  • The liquidation price (gg_price) is rounded up to two decimals with Math.ceil(gg * 100) / 100 — this one's the important one. Rounding a danger threshold down would mean showing a price that's technically still safe once you're actually below the real threshold. Rounding up means the number you're shown is always at least as conservative as reality, never less.

None of these are accidental — they're the difference between "a calculator that's approximately right" and "a calculator that never quietly tells you you're safer than you are."

Where this stays a simplified model

This is a single-stock, single-position calculator, and it says so implicitly by not trying to be anything else — no blended maintenance requirements across a multi-position portfolio, no interest accrual on the loan over time, no transaction fees or taxes eating into the equity side. It also assumes the maintenance ratio you type in is exactly the number your broker actually enforces, which varies by broker, by asset class, and sometimes by how volatile the specific stock has been recently — real brokers adjust maintenance requirements for individual securities, and this tool has no idea that happened unless you update the input yourself. It's also long-only; shorting flips which side of the ledger is "the risk," and this formula set doesn't model that. And in a real forced liquidation, brokers don't always sell your entire position at exactly the computed price — fast, illiquid markets can blow through the calculated liquidation price before the order fully fills, leaving you with a worse outcome than the tidy number above suggests.

I ended up putting the cleaned-up version of this online as a small free tool if you want to run your own numbers without doing the algebra by hand: Margin Call Calculator. No sign-up, works for both the Asian collateral-ratio convention and the Western equity-ratio convention.


Available in other languages

Top comments (0)