<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BeGoodTool.com</title>
    <description>The latest articles on DEV Community by BeGoodTool.com (@joe8_lin_tw).</description>
    <link>https://dev.to/joe8_lin_tw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4050846%2F4654b120-ef4b-499b-93b6-d370d0329825.jpg</url>
      <title>DEV Community: BeGoodTool.com</title>
      <link>https://dev.to/joe8_lin_tw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joe8_lin_tw"/>
    <language>en</language>
    <item>
      <title>A "maintenance margin ratio" isn't one formula — it's two, and mixing them up gives you the wrong liquidation price</title>
      <dc:creator>BeGoodTool.com</dc:creator>
      <pubDate>Wed, 29 Jul 2026 07:02:21 +0000</pubDate>
      <link>https://dev.to/joe8_lin_tw/a-maintenance-margin-ratio-isnt-one-formula-its-two-and-mixing-them-up-gives-you-the-wrong-1doc</link>
      <guid>https://dev.to/joe8_lin_tw/a-maintenance-margin-ratio-isnt-one-formula-its-two-and-mixing-them-up-gives-you-the-wrong-1doc</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two formulas hiding behind one label
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The tool branches on that explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAsianMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;kr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;now_maintenance_ratio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;now_price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;buy_quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;financing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentTotalValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now_price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;buy_quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;financing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;maintenance_margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAsianMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Total market value / loan amount (e.g. 166%)&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTotalValue&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// (Total market value - loan) / total market value (e.g. 40%)&lt;/span&gt;
    &lt;span class="c1"&gt;// i.e. Equity / Total Value&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;equity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentTotalValue&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;equity&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;currentTotalValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;locale&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solving the same inequality for price, from both directions
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;price&lt;/em&gt; 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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gg_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;financing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;buy_quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;financing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;maintenance_margin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;ratioDecimal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;maintenance_ratio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;gg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAsianMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Asian derivation: Price * Qty / Loan = 1.3  =&amp;gt;  Price = 1.3 * Loan / Qty&lt;/span&gt;
    &lt;span class="nx"&gt;gg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ratioDecimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;buy_quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Western derivation: (Price*Qty - Loan) / (Price*Qty) = 0.3&lt;/span&gt;
    &lt;span class="c1"&gt;// 1 - Loan/(Price*Qty) = 0.3&lt;/span&gt;
    &lt;span class="c1"&gt;// 0.7 = Loan/(Price*Qty)&lt;/span&gt;
    &lt;span class="c1"&gt;// Price = Loan / (0.7 * Qty)&lt;/span&gt;
    &lt;span class="c1"&gt;// General form: Price = Loan / ((1 - Ratio) * Qty)&lt;/span&gt;
    &lt;span class="nx"&gt;gg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;ratioDecimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;buy_quantity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both branches are the same move — take the maintenance-ratio inequality, substitute &lt;code&gt;Price × Quantity&lt;/code&gt; for "current value," and isolate &lt;code&gt;Price&lt;/code&gt; — 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra margin reduces the loan, not the equity
&lt;/h2&gt;

&lt;p&gt;There's a modeling decision buried in one line that's easy to read past: &lt;code&gt;loanAmount = financing.value - maintenance_margin.value&lt;/code&gt;. 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 (&lt;code&gt;value / loan&lt;/code&gt;) 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."&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isAsianMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Total / (Loan - Add) = Target  =&amp;gt;  Add = Loan - (Total / Target)&lt;/span&gt;
  &lt;span class="nx"&gt;needValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;currentTotalValue&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;targetDecimal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// (Total - (Loan - Add)) / Total = Target  =&amp;gt;  Add = Loan - Total * (1 - Target)&lt;/span&gt;
  &lt;span class="nx"&gt;needValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;loanAmount&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;currentTotalValue&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;targetDecimal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  Rounding decisions that matter more than they look
&lt;/h2&gt;

&lt;p&gt;Three different roundings show up for three different reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The initial equity (&lt;code&gt;self_provided&lt;/code&gt;) is rounded &lt;strong&gt;up&lt;/strong&gt; with &lt;code&gt;Math.ceil&lt;/code&gt; — 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.&lt;/li&gt;
&lt;li&gt;The computed loan amount (&lt;code&gt;financing&lt;/code&gt;) is rounded &lt;strong&gt;down&lt;/strong&gt; with &lt;code&gt;Math.floor&lt;/code&gt; — same logic from the other side, since equity + loan should never silently exceed the position's actual cost.&lt;/li&gt;
&lt;li&gt;The liquidation price (&lt;code&gt;gg_price&lt;/code&gt;) is rounded &lt;strong&gt;up&lt;/strong&gt; to two decimals with &lt;code&gt;Math.ceil(gg * 100) / 100&lt;/code&gt; — this one's the important one. Rounding a danger threshold &lt;em&gt;down&lt;/em&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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."&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this stays a simplified model
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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: &lt;a href="https://begoodtool.com/margincall/en" rel="noopener noreferrer"&gt;Margin Call Calculator&lt;/a&gt;. No sign-up, works for both the Asian collateral-ratio convention and the Western equity-ratio convention.&lt;/p&gt;




&lt;h2&gt;
  
  
  Available in other languages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall" rel="noopener noreferrer"&gt;融資維持率計算機&lt;/a&gt; — 繁體中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/cn" rel="noopener noreferrer"&gt;融资维持率计算器&lt;/a&gt; — 简体中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/en" rel="noopener noreferrer"&gt;Margin Call Calculator&lt;/a&gt; — English&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/jp" rel="noopener noreferrer"&gt;信用買い維持率計算機&lt;/a&gt; — 日本語&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/kr" rel="noopener noreferrer"&gt;신용융자 담보비율 계산기&lt;/a&gt; — 한국어&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/fr" rel="noopener noreferrer"&gt;Calculateur Appel de Marge&lt;/a&gt; — Français&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/ru" rel="noopener noreferrer"&gt;Калькулятор Маржин-колла&lt;/a&gt; — Русский&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/de" rel="noopener noreferrer"&gt;Margin Call Rechner&lt;/a&gt; — Deutsch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/id" rel="noopener noreferrer"&gt;Kalkulator Margin Call&lt;/a&gt; — Bahasa Indonesia&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/es" rel="noopener noreferrer"&gt;Calculadora de Margin Call&lt;/a&gt; — Español&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/vi" rel="noopener noreferrer"&gt;Máy Tính Call Margin&lt;/a&gt; — Tiếng Việt&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/th" rel="noopener noreferrer"&gt;เครื่องคำนวณ Margin Call&lt;/a&gt; — ไทย&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/pl" rel="noopener noreferrer"&gt;Kalkulator Margin Call&lt;/a&gt; — Polski&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/tr" rel="noopener noreferrer"&gt;Margin Call Hesaplayıcı&lt;/a&gt; — Türkçe&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/it" rel="noopener noreferrer"&gt;Calcolatore Margin Call&lt;/a&gt; — Italiano&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/pt" rel="noopener noreferrer"&gt;Calculadora de Margin Call&lt;/a&gt; — Português&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/nl" rel="noopener noreferrer"&gt;Margin Call Calculator&lt;/a&gt; — Nederlands&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/margincall/uk" rel="noopener noreferrer"&gt;Калькулятор Margin Call&lt;/a&gt; — Українська&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why signed binary ranges are asymmetric (I only really got it after building a converter)</title>
      <dc:creator>BeGoodTool.com</dc:creator>
      <pubDate>Wed, 29 Jul 2026 02:00:02 +0000</pubDate>
      <link>https://dev.to/joe8_lin_tw/why-signed-binary-ranges-are-asymmetric-i-only-really-got-it-after-building-a-converter-5e49</link>
      <guid>https://dev.to/joe8_lin_tw/why-signed-binary-ranges-are-asymmetric-i-only-really-got-it-after-building-a-converter-5e49</guid>
      <description>&lt;p&gt;I've "known" two's complement since a CS101 lecture — flip the bits, add one, done. But I didn't really internalize the range-checking part until I tried to build a small calculator that converts between decimal and N-bit binary (showing 1's and 2's complement side by side), and had to handle &lt;em&gt;arbitrary&lt;/em&gt; bit widths instead of the fixed int8/int16/int32 everyone just memorizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part everyone skips: range checking
&lt;/h2&gt;

&lt;p&gt;For an N-bit signed number, the range is asymmetric: &lt;code&gt;-2^(N-1)&lt;/code&gt; to &lt;code&gt;2^(N-1) - 1&lt;/code&gt;. For 8 bits that's -128 to 127, not -127 to 127. The reason: there's only one all-zero bit pattern (that's 0), so the "extra" negative slot that would otherwise be wasted on a redundant zero goes to the most negative number instead.&lt;/p&gt;

&lt;p&gt;That asymmetry means "does this number fit in N bits" isn't a simple &lt;code&gt;abs(num) &amp;lt;= 2^(N-1) - 1&lt;/code&gt; check — the bound is different depending on sign:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;limitNum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;numLen&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numLen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;baseNum&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// 127 for 8 bits&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;minNum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;baseNum&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// -128 for 8 bits&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;maxNum&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;minNum&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Miss this and your calculator will correctly accept -128 in 8 bits, but also let +128 slide through as if it fit — or worse, silently wrap around and hand back a nonsense value instead of telling the user it's out of range.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flip the bits, then add one — except "add one" isn't trivial in string-land
&lt;/h2&gt;

&lt;p&gt;Once a number is in binary, its two's complement is "invert every bit, then add 1." Trivial with actual integers — but I was storing binary as strings (so I could show arbitrary bit widths padded with leading zeros), which means "add 1" has to be done by hand, propagating the carry bit by bit from the right:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// carry the 1, keep going left&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// found a 0, flip it, carry absorbed, done&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;bits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// all 1s overflowed — technically wraps around&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is exactly what a hardware full-adder does when adding 1 to a binary number: propagate the carry until it hits a bit that stops it. Writing it out in string form makes visible something that's normally hidden inside the &lt;code&gt;+&lt;/code&gt; operator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going backwards is the same trick, reversed
&lt;/h2&gt;

&lt;p&gt;The calculator also needs to go the other direction — from a two's complement bit pattern back to the original magnitude, which is useful when you're staring at a hex dump and need to know what negative number it actually represents. It's the same two operations, just chained to get back to source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fromTwosComplement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;complement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inverted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;complement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bit&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inverted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Invert, add one, done. Two's complement is its own inverse operation, which is a big part of why nearly every CPU uses it: subtraction becomes addition of a complement, so there's no separate circuitry needed just for negative numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I actually use this
&lt;/h2&gt;

&lt;p&gt;I don't reach for a two's complement calculator often, but the few times a year I do — debugging a serialization bug, or double-checking a bitwise op in a language with unfamiliar int-width rules — it's genuinely useful to see binary, 1's complement, 2's complement, and decimal side by side instead of working it out by hand or trusting a REPL's implicit int width. I cleaned up the version I built for that into a small free tool: &lt;a href="https://begoodtool.com/binary/en" rel="noopener noreferrer"&gt;Two's Complement Calculator&lt;/a&gt;. No sign-up, works for any bit width you throw at it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Available in other languages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary" rel="noopener noreferrer"&gt;二進制補數計算機&lt;/a&gt; — 繁體中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/cn" rel="noopener noreferrer"&gt;二进制补码计算器&lt;/a&gt; — 简体中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/en" rel="noopener noreferrer"&gt;Two's Complement Calculator&lt;/a&gt; — English&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/jp" rel="noopener noreferrer"&gt;2の補数計算機&lt;/a&gt; — 日本語&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/kr" rel="noopener noreferrer"&gt;2의 보수 계산기&lt;/a&gt; — 한국어&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/fr" rel="noopener noreferrer"&gt;Calculateur de complément binaire&lt;/a&gt; — Français&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/ru" rel="noopener noreferrer"&gt;Калькулятор двоичного дополнительного кода&lt;/a&gt; — Русский&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/de" rel="noopener noreferrer"&gt;Zweierkomplement-Rechner&lt;/a&gt; — Deutsch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/id" rel="noopener noreferrer"&gt;Kalkulator Komplement Bilangan Biner&lt;/a&gt; — Bahasa Indonesia&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/es" rel="noopener noreferrer"&gt;Calculadora de Complemento a Dos&lt;/a&gt; — Español&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/vi" rel="noopener noreferrer"&gt;Máy Tính Bù Số Nhị Phân&lt;/a&gt; — Tiếng Việt&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/th" rel="noopener noreferrer"&gt;เครื่องคำนวณคอมพลีเมนต์เลขฐานสอง&lt;/a&gt; — ไทย&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/pl" rel="noopener noreferrer"&gt;Kalkulator uzupełnień liczb binarnych&lt;/a&gt; — Polski&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/tr" rel="noopener noreferrer"&gt;İkili Tamamlayıcı Hesap Makinesi&lt;/a&gt; — Türkçe&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/it" rel="noopener noreferrer"&gt;Calcolatrice di Complementi Binari&lt;/a&gt; — Italiano&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/pt" rel="noopener noreferrer"&gt;Calculadora de Complemento de Dois&lt;/a&gt; — Português&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/nl" rel="noopener noreferrer"&gt;Binaire Aanvullingscalculator&lt;/a&gt; — Nederlands&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/binary/uk" rel="noopener noreferrer"&gt;Калькулятор Доповнень Двійкових Чисел&lt;/a&gt; — Українська&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Turns out "fancy Instagram fonts" are just Unicode — here's how I built a generator for it</title>
      <dc:creator>BeGoodTool.com</dc:creator>
      <pubDate>Tue, 28 Jul 2026 09:01:37 +0000</pubDate>
      <link>https://dev.to/joe8_lin_tw/turns-out-fancy-instagram-fonts-are-just-unicode-heres-how-i-built-a-generator-for-it-31oo</link>
      <guid>https://dev.to/joe8_lin_tw/turns-out-fancy-instagram-fonts-are-just-unicode-heres-how-i-built-a-generator-for-it-31oo</guid>
      <description>&lt;p&gt;A while back someone half-jokingly asked if I could make a tool that turns "hello" into "𝓱𝓮𝓵𝓵𝓸" for their Instagram bio. My first instinct was "that's just a custom font" — but it's not. You can't swap fonts inside a plain text field on Instagram, TikTok, or Discord. So how do all those stylized bios actually work?&lt;/p&gt;

&lt;p&gt;Turns out the trick has nothing to do with fonts. It's Unicode.&lt;/p&gt;

&lt;h2&gt;
  
  
  The block nobody tells you about: Mathematical Alphanumeric Symbols
&lt;/h2&gt;

&lt;p&gt;Unicode reserves a whole range (U+1D400–U+1D7FF) called &lt;em&gt;Mathematical Alphanumeric Symbols&lt;/em&gt;. It exists so mathematicians can write 𝐀 (bold), 𝐴 (italic), 𝒜 (script), 𝔄 (fraktur) as genuinely distinct characters instead of relying on rich-text formatting. Nothing stops you from typing them into a regular text field, though — they render exactly like normal text, no font, no app support required.&lt;/p&gt;

&lt;p&gt;So a "fancy font converter" is really just a character-substitution cipher against a lookup table. For every style I built a 62-character string covering A–Z, a–z, 0–9, mapped 1:1 onto the matching styled code points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fontsMapping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serifBold&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;𝐀𝐁𝐂𝐃𝐄𝐅𝐆𝐇𝐈𝐉𝐊𝐋𝐌𝐍𝐎𝐏𝐐𝐑𝐒𝐓𝐔𝐕𝐖𝐗𝐘𝐙𝐚𝐛𝐜𝐝𝐞𝐟𝐠𝐡𝐢𝐣𝐤𝐥𝐦𝐧𝐨𝐩𝐪𝐫𝐬𝐭𝐮𝐯𝐰𝐱𝐲𝐳𝟎𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fraktur&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="na"&gt;map&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;𝔄𝔅ℭ𝔇𝔈𝔉𝔊ℌℑ𝔍𝔎𝔏𝔐𝔑𝔒𝔓𝔔ℜ𝔖𝔗𝔘𝔙𝔚𝔛𝔜ℨ𝔞𝔟𝔠𝔡𝔢𝔣𝔤𝔥𝔦𝔧𝔨𝔩𝔪𝔫𝔬𝔭𝔮𝔯𝔰𝔱𝔲𝔳𝔴𝔵𝔶𝔷0123456789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// ...30 more of these&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;convertString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mapArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Array.from, not split() — more on that below&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;mapArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;mapArray&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things bit me while building this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;Array.from()&lt;/code&gt; instead of &lt;code&gt;.split('')&lt;/code&gt;.&lt;/strong&gt; A lot of these code points live above U+FFFF, so they're encoded as surrogate pairs in JS strings. &lt;code&gt;map.split('')&lt;/code&gt; slices a pair in half and hands you back mangled characters. &lt;code&gt;Array.from()&lt;/code&gt; iterates by code point, which is what you actually want here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Not every style has a full alphabet.&lt;/strong&gt; Some Unicode "fonts" — small caps, superscript, the currency-symbol style — only exist for a subset of letters. There's no true Unicode superscript "Q," for instance, so I substituted the closest visual look-alike from a completely different block. For those styles it's not really a clean 1:1 cipher, it's closer to visual forgery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The weird one: Zalgo text
&lt;/h2&gt;

&lt;p&gt;The glitch/cursed-text effect (t̸h̶i̵s̴ ̶s̴o̷r̶t̵ ̶o̴f̵ ̸t̶h̷i̴n̶g̸) isn't from the same character block at all — it's &lt;em&gt;combining diacritical marks&lt;/em&gt;. Normally these stack a single accent on top of a letter (the mark that turns &lt;code&gt;e&lt;/code&gt; into &lt;code&gt;é&lt;/code&gt;). Nothing stops you from stacking dozens of them on the same character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zalgoUp&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̍&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̎&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̄&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* ...36 more */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zalgoMid&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̕&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̛&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̀&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zalgoDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̖&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̗&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̘&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numUp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;numUp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;zalgoUp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;zalgoUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// same idea for the mid and down mark sets&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Randomly stack 1–2 marks above, 0–1 in the middle, and 1–2 below every character, and you get the "reality is glitching" look. It's not elegant — it's controlled chaos — but the randomness is exactly what sells the effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other decorations are combining marks too
&lt;/h2&gt;

&lt;p&gt;Strikethrough, underline, and overline use the same combining-character trick, just with a single mark appended after each letter instead of a lookup substitution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;strikethrough&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decorator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̶&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;underline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="na"&gt;decorator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;̲&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;"h" + "̶"&lt;/code&gt; renders as h̶. No lookup table needed — just append and skip spaces, since a combining mark attached to a space usually renders oddly or gets silently dropped by the renderer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this breaks more than it should
&lt;/h2&gt;

&lt;p&gt;Once you know the trick, the limitations make sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;These are still plain Unicode characters to a screen reader, not letters — text-to-speech often can't pronounce them correctly.&lt;/li&gt;
&lt;li&gt;Search engines and in-app search generally won't match "𝓱𝓮𝓵𝓵𝓸" against "hello," so you lose searchability the moment you use it.&lt;/li&gt;
&lt;li&gt;Devices or fonts missing glyphs for the rarer blocks fall back to the classic empty box (☒).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that stops it from being fun — but it's worth knowing you're trading "cool font" for "no longer quite text" in the eyes of most software that touches it.&lt;/p&gt;

&lt;p&gt;I turned the whole thing (30+ styles plus the Zalgo generator) into a small free tool if you want to play with it without building your own lookup table: &lt;a href="https://begoodtool.com/ig-font-converter/en" rel="noopener noreferrer"&gt;Instagram Font Generator&lt;/a&gt;. No sign-up, it's a static page.&lt;/p&gt;




&lt;h2&gt;
  
  
  Available in other languages
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter" rel="noopener noreferrer"&gt;Instagram字體轉換器&lt;/a&gt; — 繁體中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/cn" rel="noopener noreferrer"&gt;Instagram字体生成器&lt;/a&gt; — 简体中文&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/en" rel="noopener noreferrer"&gt;Instagram Font Generator&lt;/a&gt; — English&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/jp" rel="noopener noreferrer"&gt;Instagramフォント変換ツール&lt;/a&gt; — 日本語&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/kr" rel="noopener noreferrer"&gt;인스타 폰트 변환기&lt;/a&gt; — 한국어&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/fr" rel="noopener noreferrer"&gt;Polices Instagram&lt;/a&gt; — Français&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/ru" rel="noopener noreferrer"&gt;Шрифты для Instagram&lt;/a&gt; — Русский&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/de" rel="noopener noreferrer"&gt;Instagram Schriftarten&lt;/a&gt; — Deutsch&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/id" rel="noopener noreferrer"&gt;Generator Font Instagram&lt;/a&gt; — Bahasa Indonesia&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/es" rel="noopener noreferrer"&gt;Fuentes para Instagram&lt;/a&gt; — Español&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/vi" rel="noopener noreferrer"&gt;Phông chữ Instagram&lt;/a&gt; — Tiếng Việt&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/th" rel="noopener noreferrer"&gt;เปลี่ยนฟอนต์ Instagram&lt;/a&gt; — ไทย&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/pl" rel="noopener noreferrer"&gt;Czcionki Instagram&lt;/a&gt; — Polski&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/tr" rel="noopener noreferrer"&gt;Instagram Yazı Tipleri&lt;/a&gt; — Türkçe&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/it" rel="noopener noreferrer"&gt;Font per Instagram&lt;/a&gt; — Italiano&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/pt" rel="noopener noreferrer"&gt;Fontes para Instagram&lt;/a&gt; — Português&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/nl" rel="noopener noreferrer"&gt;Instagram Lettertypen&lt;/a&gt; — Nederlands&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://begoodtool.com/ig-font-converter/uk" rel="noopener noreferrer"&gt;Шрифти для Instagram&lt;/a&gt; — Українська&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
