Lesson 02 / 17
Qualitative and Quantitative Approaches
The same 47 items are run through two scales: the monetary model computes single and annualized loss expectancy in fictional units, while the five-by-five qualitative matrix reduces the items to three levels, ties 479 of the 1,081 item pairs and reverses 52 of them, writes the 184.80-unit item as medium and the 96.00-unit item as high, and opens a 745.20-unit gap in the outcome of the same ten items chosen with the same effort.
Published Updated
In this lesson
- Names and calculates the monetary model: single loss expectancy, annual rate of occurrence and annualized loss expectancy
- Runs the qualitative band matrix on the same set of items and counts the number of pairs that fall into a tie
- Compares the pair the two scales rank in reverse and each scale's resilience against estimation drift
Contents
The previous lesson produced and ranked the 47-item list, but the frequency and impact in each row came not from a measurement but from an estimate. There are two common ways to estimate: the qualitative approach, which places items into bands instead of numbers, and the quantitative approach, which splits the loss into asset value and loss ratio. This lesson runs both on the same list. The question is not which one is correct — both work from the same uncertain input — but how many places apart the same data ranks things and how many units that difference costs in the budget. The priority list is not a product of the data; it is a product of the scale applied to the data.
Two Scales
The quantitative approach splits the loss into two parts. Single loss expectancy is what is lost when the event happens once, and it is the product of asset value and the exposure ratio: a 35 percent exposure ratio on a 3,000-fictional-unit database writes a single loss of 1,050 units. Annualized loss expectancy is the product of the single loss and the annual rate of occurrence. The previous lesson’s “impact” and “risk” columns are exactly these; the name changes, the number does not.
The qualitative approach reduces the same two inputs to bands and feeds the band pair into a matrix. Each cell gives an ordinal level. Levels are an order, not a scale: the distance between “high” and “medium” is undefined, and two “medium”s cannot be added together.
- RM7. Seven threats, ten assets and all the coefficients are the model; the unit is the fictional unit.
- RM8. Asset value is assumed to be derived from the business description and is fixed in the model.
- RM9. Single loss expectancy is the product of asset value and exposure ratio; annualized loss expectancy is the product of single loss and annual frequency.
- RM10. The qualitative matrix is five by five and carries four levels; the levels are ordinal, they cannot be summed.
- RM11. Baseline frequency is an estimate; the drift generator gives each threat a coefficient between 0.75 and 1.25, the seed is visible and the output does not change from run to run.
// risk/scale.mjs — the same 47 items, two scales: the qualitative band matrix and the monetary // model. THIS IS A MODEL; there is no real inventory, no real incident log and no real currency, // the unit is the "fictional unit". // RM7: threat row: name | annual rate of occurrence (baseline) | exposure ratio const THREAT = ` credential-theft 0.30 0.35 malicious-code 0.50 0.25 misconfiguration 0.80 0.15 insider-misuse 0.10 0.40 service-disruption 0.40 0.20 physical-access 0.06 0.50 supply-chain 0.08 0.45` .trim().split("\n").map((r) => { const [name, s, m] = r.trim().split(/\s+/); return { name, baseFreq: +s, exposureRatio: +m }; }); // RM8: asset row: name | asset value | exposure multiplier | threat mask (seven digits) const ASSET = ` field-laptop 900 1.6 1111011 branch-endpoint 600 1.2 1111110 measurement-collector 750 1.4 0111110 processing-server 1800 0.6 1111101 perimeter-network 1200 1.8 0011100 identity-directory 2400 1.0 1011100 cloud-account 2000 1.5 1011100 subscriber-database 3000 0.4 1011100 field-application 1400 1.1 1111001 supplier-connection 1000 1.3 1001101` .trim().split("\n").map((r) => { const [name, v, k, mask] = r.trim().split(/\s+/); return { name, value: +v, exposureMult: +k, mask }; }); // RM9: monetary model. Single loss expectancy (SLE) = asset value x exposure ratio; annualized // loss expectancy (ALE) = SLE x annual frequency. These are the previous lesson's "impact" and // "risk" columns; the name changed, the number did not. export const ITEM = []; for (const v of ASSET) for (const [j, t] of THREAT.entries()) if (v.mask[j] === "1") { const freq = +(t.baseFreq * v.exposureMult).toFixed(3), sle = +(v.value * t.exposureRatio).toFixed(1); ITEM.push({ v, t, j, freq, sle, ale: +(freq * sle).toFixed(2) }); } // RM10: qualitative scale. Frequency and SLE are each reduced to a band; the band pair looks up // a matrix cell; the cell gives one of four levels. Levels are ordinal, they cannot be summed. const band = (x, s) => s.findIndex((u) => x < u) + 1 || s.length + 1; export const FREQ_BOUNDS = [0.10, 0.25, 0.50, 1.00], SLE_BOUNDS = [180, 315, 450, 700]; export const LEVEL = ["low", "medium", "high", "critical"]; // Row = SLE band (5 to 1), column = frequency band (1 to 5). The digit is the LEVEL index. export const MATRIX = ["12233", "11223", "01122", "00112", "00011"]; export const freqBand = (k) => band(k.freq, FREQ_BOUNDS); export const sleBand = (k) => band(k.sle, SLE_BOUNDS); export const level = (k) => +MATRIX[5 - sleBand(k)][freqBand(k) - 1]; for (const k of ITEM) { k.freqBand = freqBand(k); k.sleBand = sleBand(k); k.level = level(k); } export const TOTAL = +ITEM.reduce((a, k) => a + k.ale, 0).toFixed(2); export const sortBy = (f) => ITEM.map((k, i) => ({ k, i })) .sort((a, b) => f(b.k) - f(a.k) || a.i - b.i).map((x) => x.k); export const position = (L, k) => L.indexOf(k) + 1; // RM11: estimation drift. Baseline frequency is an estimate, not a measurement; the generator // below gives each threat a coefficient between 0.75 and 1.25. The seed is visible, the output // does not change. let seed = 20250401; const rand = () => (seed = (seed * 1103515245 + 12345) % 2147483648) / 2147483648; export const DRIFT = THREAT.map(() => +(0.75 + rand() * 0.5).toFixed(3)); export const drifted = (k) => { const freq = +(k.freq * DRIFT[k.j]).toFixed(3); return { freq, ale: +(freq * k.sle).toFixed(2), level: +MATRIX[5 - k.sleBand][band(freq, FREQ_BOUNDS) - 1] }; };
Two Scales on the Same List
// risk/compare.mjs — the qualitative level and the annualized loss expectancy race on the same list import { ITEM, TOTAL, LEVEL, MATRIX, FREQ_BOUNDS, SLE_BOUNDS, DRIFT, drifted, sortBy, position } from "./scale.mjs"; const y = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("").trimEnd()); const BY_ALE = sortBy((k) => k.ale); // monetary: annualized loss expectancy const BY_LEVEL = sortBy((k) => k.level); // qualitative: level, ties keep list order console.log(`${ITEM.length} items, total annualized loss expectancy ${TOTAL} fictional units; ` + `band boundaries ${FREQ_BOUNDS.join("/")} and ${SLE_BOUNDS.join("/")}`); const A = [-9, 9, 9, 9, 9, 9]; console.log("\n1. qualitative matrix (row: single-loss band 5..1, column: frequency band 1..5)"); y(A, "sle\\freq", "1", "2", "3", "4", "5"); MATRIX.forEach((r, i) => y(A, String(5 - i), ...[...r].map((c) => LEVEL[+c]))); const freq5 = ITEM.filter((k) => k.freqBand === 5), sle5 = ITEM.filter((k) => k.sleBand === 5); console.log(`${new Set(ITEM.map((k) => `${k.sleBand}${k.freqBand}`)).size} of 25 cells are filled; ` + `of the ${freq5.length} items with frequency band 5, the highest single-loss band is ` + `${Math.max(...freq5.map((k) => k.sleBand))}, of the ${sle5.length} items with single-loss band 5, ` + `the highest frequency band is ${Math.max(...sle5.map((k) => k.freqBand))}`); const B = [-8, 7, 10, 10, 6, 12, 8]; console.log("\n2. per level"); y(B, "level", "items", "smallest", "largest", "ratio", "total ALE", "share %"); for (const [i, name] of LEVEL.entries()) { const g = ITEM.filter((k) => k.level === i); if (g.length === 0) { y(B, name, 0, "-", "-", "-", "0.00", "0.0"); continue; } const lo = Math.min(...g.map((k) => k.ale)), hi = Math.max(...g.map((k) => k.ale)); const t = g.reduce((a, k) => a + k.ale, 0); y(B, name, g.length, lo.toFixed(2), hi.toFixed(2), (hi / lo).toFixed(1), t.toFixed(2), ((t / TOTAL) * 100).toFixed(1)); } const HIGH = ITEM.filter((k) => k.level === 2).sort((a, b) => b.ale - a.ale); const C = [-22, -21, 5, 5, 10, 5]; console.log("\n3. the part of the 'high' level that falls back in the monetary order"); y(C, "asset", "threat", "f-b", "s-b", "ALE", "N"); for (const k of HIGH.slice(8)) y(C, k.v.name, k.t.name, k.freqBand, k.sleBand, k.ale.toFixed(2), position(BY_ALE, k)); console.log(`the first ${HIGH.filter((k, i) => position(BY_ALE, k) === i + 1).length} items of this level ` + `are in the same place in the monetary order too`); const midTop = ITEM.filter((k) => k.level === 1).reduce((a, k) => (k.ale > a.ale ? k : a)); console.log(`the "medium" item with the highest ALE: ${midTop.v.name} / ${midTop.t.name} ` + `${midTop.ale.toFixed(2)} units, ALE rank ${position(BY_ALE, midTop)}`); const D = [-42, 8]; console.log("\n4. the gap between the two scales"); const pair = (f) => { let n = 0; for (let a = 0; a < ITEM.length; a++) for (let b = a + 1; b < ITEM.length; b++) if (f(ITEM[a], ITEM[b])) n++; return n; }; y(D, "total item pairs", pair(() => true)); y(D, "pairs tied in the qualitative scale", pair((a, b) => a.level === b.level)); y(D, "pairs the two scales rank in reverse", pair((a, b) => (a.level - b.level) * (a.ale - b.ale) < 0)); y(D, "levels used in the qualitative scale", new Set(ITEM.map((k) => k.level)).size + "/4"); y(D, "how many of the top ten are shared", BY_LEVEL.slice(0, 10).filter((k) => BY_ALE.slice(0, 10).includes(k)).length); const E = [-42, 8]; const top = (L) => +L.reduce((a, k) => a + k.ale, 0).toFixed(2); console.log("\n5. if the same effort picks ten items (the arbitrariness of a tie)"); y(E, "top ten by monetary order", top(BY_ALE.slice(0, 10))); y(E, "qualitative: best ten from high level", top(HIGH.slice(0, 10))); y(E, "qualitative: worst ten from high level", top(HIGH.slice(-10))); y(E, "gap from arbitrariness", +(top(HIGH.slice(0, 10)) - top(HIGH.slice(-10))).toFixed(2)); const F = [-47, 8]; const BY_ALE_DRIFT = sortBy((k) => drifted(k).ale); console.log(`\n6. estimation drift (coefficient per threat: ${DRIFT.join(" ")})`); y(F, "items whose ALE rank changes", ITEM.filter((k) => position(BY_ALE, k) !== position(BY_ALE_DRIFT, k)).length); y(F, "largest rank shift", Math.max(...ITEM.map((k) => Math.abs(position(BY_ALE, k) - position(BY_ALE_DRIFT, k))))); y(F, "how many of the top ten by money stay the same", BY_ALE_DRIFT.slice(0, 10).filter((k) => BY_ALE.slice(0, 10).includes(k)).length); y(F, "items whose qualitative level changes", ITEM.filter((k) => drifted(k).level !== k.level).length);
47 items, total annualized loss expectancy 5768.61 fictional units; band boundaries 0.1/0.25/0.5/1 and 180/315/450/700 1. qualitative matrix (row: single-loss band 5..1, column: frequency band 1..5) sle\freq 1 2 3 4 5 5 medium high high critical critical 4 medium medium high high critical 3 low medium medium high high 2 low low medium medium high 1 low low low medium medium 18 of 25 cells are filled; of the 4 items with frequency band 5, the highest single-loss band is 2, of the 8 items with single-loss band 5, the highest frequency band is 3 2. per level level items smallest largest ratio total ALE share % low 5 21.60 57.60 2.7 181.50 3.1 medium 28 38.88 184.80 4.8 2705.71 46.9 high 14 96.00 360.00 3.8 2881.40 49.9 critical 0 - - - 0.00 0.0 3. the part of the 'high' level that falls back in the monetary order asset threat f-b s-b ALE N field-application credential-theft 3 4 161.70 13 subscriber-database misconfiguration 3 4 144.00 15 processing-server malicious-code 3 4 135.00 17 subscriber-database credential-theft 2 5 126.00 21 cloud-account insider-misuse 2 5 120.00 22 identity-directory insider-misuse 2 5 96.00 25 the first 8 items of this level are in the same place in the monetary order too the "medium" item with the highest ALE: field-application / misconfiguration 184.80 units, ALE rank 9 4. the gap between the two scales total item pairs 1081 pairs tied in the qualitative scale 479 pairs the two scales rank in reverse 52 levels used in the qualitative scale 3/4 how many of the top ten are shared 7 5. if the same effort picks ten items (the arbitrariness of a tie) top ten by monetary order 2463.5 qualitative: best ten from high level 2404.4 qualitative: worst ten from high level 1659.2 gap from arbitrariness 745.2 6. estimation drift (coefficient per threat: 1.116 0.896 1.167 0.756 0.814 0.759 1.191) items whose ALE rank changes 37 largest rank shift 7 how many of the top ten by money stay the same 8 items whose qualitative level changes 8
The numbers are in the measurement class; its inputs are RM7–RM11.
The Corner That Never Fills
The matrix defines four levels and the program uses three of them. The “critical” cells stay empty, because those cells demand both high frequency and high single loss, and the two conditions never meet in the same item: of the four items with frequency band 5, the highest single-loss band is 2; of the eight items with single-loss band 5, the highest frequency band is 3. Eighteen of twenty-five cells are filled, but the filled cells spread out on both sides of the diagonal.
This shows that the scale’s resolution narrows relative to the data: 47 items are described with three words, and the most crowded word is “medium” — 28 items, sixty percent of the list, sit in a single box.
The Spread Inside the Same Level
The second table gives this lesson’s main finding. The annualized loss expectancy of the 14 items in the “high” level ranges between 96.00 and 360.00 units — a 3.8-fold spread. The spread is even wider in the “medium” level: between 38.88 and 184.80, a 4.8-fold spread.
The real result is where the two levels intersect. The “medium” item with the highest annualized loss expectancy is the misconfiguration on the field application: 184.80 units, and ninth in the monetary order. In the same list, the insider-misuse item on the identity directory is written as “high” and carries 96.00 units, and it is twenty-fifth in the monetary order. The qualitative scale ranks the second one ahead; the monetary model ranks the first one ahead by sixteen places.
The reversal is not a coincidence. The qualitative matrix bands single loss and frequency separately; when an item goes to an extreme in a single dimension, the cell carries it upward without looking at what the product gives. The third table separates out these items: the first eight of the “high” level are also the first eight in the monetary order; the remaining six are scattered between the 13th and 25th places, and three of them have single-loss band 5 and frequency band 2.
The fourth table measures the same phenomenon by pair count. 47 items produce 1,081 pairs; the qualitative scale drops 479 of them into a tie, and in 52 pairs the two scales say the opposite of each other. A tie is a deficiency, a reversal is a contradiction; the first defers the decision, the second delivers the wrong one.
When a Tie Turns Into Budget
The fifth table writes the cost of the tie. If the program can handle ten items, the monetary order picks the top ten and targets 2,463.50 units. The qualitative order picks ten of the 14 items in the “high” level, but it does not say which ten: the best choice comes to 2,404.40, the worst to 1,659.20 units.
The 745.20-unit gap between them is the arbitrariness the scale leaves behind. The same list, the same effort and the same number of items; what determines the outcome is the order in which the list was written. The good end of the qualitative approach comes within 59.10 units of the monetary model’s result; the bad end is 804.30 units away. The scale is not wrong, it is incomplete: it carries the decision so far and leaves the last step to an unnamed choice.
Facing Estimation Drift
The sixth table measures the monetary model’s own weakness. When the baseline frequencies are shaken within a 25 percent band — the generator is written into the lesson, the seed is visible — 37 items change place in the monetary ranking and the largest shift is seven positions. Eight of the top ten stay in place; the band that moves is the middle one.
The same drift changes only 8 items’ level in the qualitative scale. The band boundaries absorb the movement in the input: a frequency between 0.36 and 0.44 falls into the same band. The loss of resolution turns into a gain here — a small number of boxes reacts less to input error.
When the two tables are read together, the choice becomes clear. The monetary model makes a finer distinction, and part of that distinction is not real but estimation noise; the 37-item shift is proof of it. The qualitative model withstands the noise, and in exchange it says nothing in 479 pairs. Both put the same uncertainty in a different place: one in the digits of the number, the other inside the box. Unless which approach was used is written down, how much of the ranking came from the data cannot be known.
Summary
- The monetary model splits the loss in two: single loss expectancy is the product of asset value and exposure ratio, annualized loss expectancy is the product of single loss and annual frequency; the total is 5,768.61 fictional units.
- The five-by-five qualitative matrix defines four levels and the program uses three of them; 18 of 25 cells are filled and “critical” stays empty, because high frequency and high single loss never meet in the same item.
- The spread inside the same level runs between 3.8-fold and 4.8-fold; the 184.80-unit item is written as “medium,” the 96.00-unit item as “high,” and sixteen places separate them.
- 479 of the 1,081 item pairs fall into a tie in the qualitative scale, and in 52 the two scales say the opposite of each other; only seven of the top ten are shared.
- The same ten-item effort targets 2,463.50 units by the monetary order and between 1,659.20 and 2,404.40 units by the qualitative order; the 745.20-unit gap is the choice the scale does not name.
- When the frequency estimate is shaken within a 25 percent band, 37 items change place in the monetary order and only 8 items’ level changes in the qualitative scale: the loss of resolution gives resilience against input error.
Next Step
Both lessons carry the same silent assumption: there was a single way to handle each item, and that way reduced risk at a fixed rate. In reality, a risk item is answered in four separate ways — adding a control to mitigate it, transferring its cost through a contract, accepting it as it is, and avoiding it by dropping the work that creates the risk. All four are spent from the same budget, and the risk they reduce per unit differs. The next lesson runs all four on the same list, and separately counts which items the transfer fails to hand off.
To keep your progress and take notes, Log in
My notes
Log in to take notes.