FunctionCosineSimilarity
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © RicardoSantos

//@version=5

// @description Cosine Similarity method.
library("FunctionCosineSimilarity")

import RicardoSantos/DebugConsole/6 as console
[__T, __C] = console.init(25)

// @function Measure the similarity of 2 vectors.
// @param sample_a float array, values.
// @param sample_b float array, values.
// @returns float.
export function (float[] sample_a, float[] sample_b) => //{
    int _size_a = array.size(sample_a)
    int _size_b = array.size(sample_b)
    //
    switch
        (_size_a < 1) => runtime.error('FunctionCosineSimilarity -> function(): "sample_a" has invalid size.')
        (_size_b < 1) => runtime.error('FunctionCosineSimilarity -> function(): "sample_b" has invalid size.')
        (_size_a != _size_b) => runtime.error('FunctionCosineSimilarity -> function(): "sample_a" and "sample_a" size is not symmetric.')
    //
    float _dot = 0.0
    float _norm_a = 0.0
    float _norm_b = 0.0
    for _i = 0 to _size_a-1
        float _ai = array.get(sample_a, _i)
        float _bi = array.get(sample_b, _i)
        _dot += _ai * _bi
        _norm_a += math.pow(_ai, 2.0)
        _norm_b += math.pow(_bi, 2.0)
    _dot / (math.sqrt(_norm_a) * math.sqrt(_norm_b))
//{ usage
// var a = array.new_float(10)
// var b = array.new_float(10)
// array.unshift(a, nz(close/ta.ema(close, 10), 0.0)), array.pop(a)
// array.unshift(b, float(math.sin(bar_index%10))), array.pop(b)
// cs = function(a, b)
// [m, u, l]= ta.bb(cs, input(200), input(2.0))
// plot(cs)
// plot(m), plot(u), plot(l)
console.queue_one(__C, str.format('{0}', function(array.from(3.0, 2, 0, 5), array.from(1.0, 0, 0, 0))))
//{ remarks:
//      https://stackoverflow.com/questions/520241/how-do-i-calculate-the-cosine-similarity-of-two-vectors
//      https://www.geeksforgeeks.org/cosine-similarity/
//}}}

// @function Dissimilarity helper function.
// @param cosim float, cosine similarity value (0 > 1)
// @returns float
export diss (float cosim) => 1.0 - cosim

console.update(__T, __C)