KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Vector Utility Class for Financial and Statistical Calculations – Part 2
PRODUCT: 4D | VERSION: 21 | PLATFORM: Mac & Win
Published On: March 20, 2026
Building on Part 1, where we introduced the basics this part focuses on Mean calculation and vector L2-Normalization. These operations are essential for preprocessing financial data such us averaging KPIs or scaling vectors for comparison in bank portfolio analysis. For the full introduction refer to Part 1, https://kb.4d.com/assetid=79947.

property defaultDimension : Integer

Class constructor
  This.defaultDimension:=3
/*
 Function createZeroVector($dimension : Integer) : 4D.Vector

 Function addVectors($vecA : 4D.Vector; $vecB : 4D.Vector) : 4D.Vector

 Function multiplyByScalar($vector : 4D.Vector; $multiplier : Real) : 4D.Vector

*/

Function calculateMean($vectorList:Collection):4D.Vector
    If($vectorList.length=0)
        return This.createZeroVector(0)
    End if
    var $total:4D.Vector
    $total:=4D.Vector.new($vectorList[0].toCollection())
    var $pos:Integer
    For($pos;1;$vectorList.length-1)
        $total:=This.addVectors($total;$vectorList[$pos])
    End for
    return This.multiplyByScalar($total;1/$vectorList.length)


Function normalizeVector($vector:4D.Vector):4D.Vector
    var $sumOfSquares:Real
    $sumOfSquares:=0
    var $index:Integer
    For($index;0;$vector.length-1)
        $sumOfSquares:=$sumOfSquares+$vector[$index]*$vector[$index]
    End for
    var $magnitude:Real
    $magnitude:=Square root($sumOfSquares)
    If($magnitude<=0.000001)
        return This.createZeroVector($vector.length)
    End if
    return This.multiplyByScalar($vector;1/$magnitude)




Example 1: Gap Analysis

In 4D, a vector is just an object . For example, if you track three KPIs : Return on Assets (ROA), Current Ratio, and Debt-to-Equity, one client’s vector might look like this: V = [0.05, 2.1, 0.4]
The Mean KPI Vector is the mathematical average of these points across an entire peer group for instance all "Small Business" clients in the "Retail" sector.
Using vectors instead of single numbers gives you a more complete picture, because it considers all KPIs together. The example below captures the correlation between these factors, giving a holistic view of whether the client is a "healthy" outlier or a "risky" one.

var $utility:cs.VectorUtility
$utility:=cs.VectorUtility.new()

// Sample client KPI vectors (normalized 0-1 scale)
// Format: [ROA, Current Ratio, Debt-to-Equity]
var $clientVectors:Collection
$clientVectors:=New collection(\
    4D.Vector.new([0.05;2.1;0.4]);\
    4D.Vector.new([0.12;1.8;1.2]);\
    4D.Vector.new([0.08;1.5;3.5])\
)

var $meanKPI:4D.Vector
$meanKPI:=$utility.calculateMean($clientVectors)

ALERT("Mean KPI Vector (Benchmark):\n"+JSON Stringify($meanKPI.toCollection()))


Mean KPI Vector = [0.083333333333333, 1.8, 1.7], this is the average vector calculated across clients.
  • If a client’s numbers are very close to [0.0833, 1.8, 1.7] => they are normal/healthy.
  • If a client’s numbers are very different => they are an outlier, could be very good or very risky


  • Use Case 2: Normalizing Vectors for Comparison
    When comparing clients, raw numbers can be misleading. A big company with $10M revenue looks very different from a small one with $100k, even if their proportions are similar. Normalization removes the “size” effect and lets you compare the shape of their performance.

    var $utility:cs.VectorUtility
    $utility:=cs.VectorUtility.new()

    // Sample KPI vectors: different client sizes

    var $enterprise:4D.Vector
    $enterprise:=4D.Vector.new([10000000;2000000;0.2]) // Large company

    var $sme:4D.Vector
    $sme:=4D.Vector.new([100000;20000;0.2]) // Small company

    // Normalize both vectors to unit length

    var $normEnterprise:4D.Vector
    $normEnterprise:=$utility.normalizeVector($enterprise)

    var $normSme:4D.Vector
    $normSme:=$utility.normalizeVector($sme)

    var $similarity:Real
    $similarity:=$normEnterprise.cosineSimilarity($normSme)

    ALERT("Normalized Enterprise: "+JSON Stringify($normEnterprise.toCollection())+"\n"+\
      "Normalized SME: "+JSON Stringify($normSme.toCollection())+"\n"+\
      "Cosine Similarity (after normalization): "+String($similarity))


    Normalized Enterprise = [0.0015811388142728,0.00031622776285456,3.1622776285456E-11]
    Normalized SME = [0.015811372489477,0.0031622744978955,3.1622744978955E-08]

    The Important Number:Cosine Similarity = 0.9999999999981
    This score tells how similar the shapes of the two companies are:

    • 1.0 = perfectly identical in shape
    • 0.9999999999981 = extremely close to perfect

    Interpretation: These two companies, despite one being huge and one being small have almost identical financial health patterns. They are very similar in risk profile:

    • Profit margins relative to their size
    • Liquidity relative to their size
    • Debt levels relative to their size