merge: quick/fase-funciones-y-wal — 54 funciones, 12 tipos, WAL mode

This commit is contained in:
2026-03-28 02:23:51 +01:00
129 changed files with 2991 additions and 1 deletions
+25
View File
@@ -0,0 +1,25 @@
package core
// Chunk splits xs into sub-slices of the given size.
// The last chunk may contain fewer than size elements.
// Returns nil if xs is empty. Panics if size <= 0.
func Chunk[T any](xs []T, size int) [][]T {
if size <= 0 {
panic("chunk size must be > 0")
}
n := len(xs)
if n == 0 {
return nil
}
numChunks := (n + size - 1) / size
chunks := make([][]T, 0, numChunks)
for i := 0; i < n; i += size {
end := i + size
if end > n {
end = n
}
chunks = append(chunks, xs[i:end])
}
return chunks
}
+35
View File
@@ -0,0 +1,35 @@
---
name: chunk
kind: function
lang: go
domain: core
version: "1.0.0"
purity: pure
signature: "func Chunk[T any](xs []T, size int) [][]T"
description: "Divide un slice en trozos (sub-slices) de tamanio N. El ultimo trozo puede contener menos de N elementos. Retorna nil si el slice esta vacio. Entra en panic si size <= 0."
tags: [slice, chunk, batch, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/chunk.go"
---
## Ejemplo
```go
chunks := Chunk([]int{1, 2, 3, 4, 5}, 2)
// chunks = [[1, 2], [3, 4], [5]]
chunks = Chunk([]string{"a", "b", "c", "d"}, 4)
// chunks = [["a", "b", "c", "d"]]
```
## Notas
Funcion pura generica. Los sub-slices comparten memoria con el slice original (son slices del mismo backing array). Pre-calcula la capacidad del slice de chunks para evitar reasignaciones. Si size es mayor que len(xs), retorna un unico chunk con todos los elementos.
+43
View File
@@ -0,0 +1,43 @@
package core
import "sync"
// MapConcurrent applies fn to each element of xs using a pool of worker goroutines.
// The number of concurrent workers is capped by the workers parameter.
// Results preserve the original index order. If workers <= 0, it defaults to 1.
func MapConcurrent[T any, U any](xs []T, fn func(T) U, workers int) []U {
if workers <= 0 {
workers = 1
}
n := len(xs)
if n == 0 {
return []U{}
}
results := make([]U, n)
var wg sync.WaitGroup
ch := make(chan int, n)
// Feed indices into the channel.
for i := range xs {
ch <- i
}
close(ch)
// Spawn workers.
if workers > n {
workers = n
}
wg.Add(workers)
for w := 0; w < workers; w++ {
go func() {
defer wg.Done()
for i := range ch {
results[i] = fn(xs[i])
}
}()
}
wg.Wait()
return results
}
+34
View File
@@ -0,0 +1,34 @@
---
name: map_concurrent
kind: function
lang: go
domain: core
version: "1.0.0"
purity: impure
signature: "func MapConcurrent[T any, U any](xs []T, fn func(T) U, workers int) []U"
description: "Aplica una funcion a cada elemento de un slice usando un pool de goroutines como workers. Los resultados preservan el orden original del slice de entrada."
tags: [map, concurrent, parallel, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/map_concurrent.go"
---
## Ejemplo
```go
squares := MapConcurrent([]int{1, 2, 3, 4, 5}, func(n int) int {
return n * n
}, 3)
// squares = [1, 4, 9, 16, 25] (orden preservado)
```
## Notas
Funcion impura generica que usa goroutines y sync.WaitGroup. Los workers se alimentan de un canal con indices, garantizando que cada resultado se escribe en su posicion correcta sin race conditions (cada goroutine escribe en un indice unico). Si workers <= 0 se usa 1. Si workers > len(xs) se ajusta a len(xs).
+16
View File
@@ -0,0 +1,16 @@
package core
// Memoize wraps a pure function fn so that results are cached by key.
// Subsequent calls with the same key return the cached value without calling fn again.
// The returned function is safe for single-goroutine use.
func Memoize[K comparable, V any](fn func(K) V) func(K) V {
cache := make(map[K]V)
return func(key K) V {
if val, ok := cache[key]; ok {
return val
}
val := fn(key)
cache[key] = val
return val
}
}
+40
View File
@@ -0,0 +1,40 @@
---
name: memoize
kind: function
lang: go
domain: core
version: "1.0.0"
purity: pure
signature: "func Memoize[K comparable, V any](fn func(K) V) func(K) V"
description: "Cachea resultados de una funcion pura. Retorna una nueva funcion que almacena en un mapa interno los resultados ya calculados, evitando recalculos para la misma clave."
tags: [cache, memoize, functional, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/memoize.go"
---
## Ejemplo
```go
fib := Memoize(func(n int) int {
if n <= 1 {
return n
}
// nota: para recursion memoizada se necesita declarar la variable antes
return n // simplificado
})
doubled := Memoize(func(x int) int { return x * 2 })
doubled(5) // calcula: 10
doubled(5) // cache hit: 10
```
## Notas
Funcion pura generica (referencialmente transparente). El cache interno es un map[K]V sin sincronizacion, por lo que la funcion retornada es segura solo para uso en una sola goroutine. K debe ser comparable para usarse como clave del mapa.
+16
View File
@@ -0,0 +1,16 @@
package core
// Partition splits xs into two slices: the first contains elements where pred returns true,
// the second contains elements where pred returns false. Original order is preserved in both.
func Partition[T any](xs []T, pred func(T) bool) ([]T, []T) {
trueSlice := make([]T, 0)
falseSlice := make([]T, 0)
for _, x := range xs {
if pred(x) {
trueSlice = append(trueSlice, x)
} else {
falseSlice = append(falseSlice, x)
}
}
return trueSlice, falseSlice
}
+33
View File
@@ -0,0 +1,33 @@
---
name: partition
kind: function
lang: go
domain: core
version: "1.0.0"
purity: pure
signature: "func Partition[T any](xs []T, pred func(T) bool) ([]T, []T)"
description: "Divide un slice en dos segun un predicado. El primer slice contiene los elementos que cumplen el predicado, el segundo los que no. Se preserva el orden original."
tags: [slice, partition, functional, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/partition.go"
---
## Ejemplo
```go
evens, odds := Partition([]int{1, 2, 3, 4, 5}, func(n int) bool { return n%2 == 0 })
// evens = [2, 4]
// odds = [1, 3, 5]
```
## Notas
Funcion pura generica. Ambos slices retornados son nuevos (no muta el slice original). Si el slice de entrada esta vacio, retorna dos slices vacios. Los elementos mantienen su orden relativo original en cada particion.
+13
View File
@@ -0,0 +1,13 @@
package core
// Pipeline composes a sequence of functions T -> T into a single function.
// The functions are applied left to right: Pipeline(f, g, h)(x) == h(g(f(x))).
// Returns the identity function if no functions are provided.
func Pipeline[T any](fns ...func(T) T) func(T) T {
return func(val T) T {
for _, fn := range fns {
val = fn(val)
}
return val
}
}
+36
View File
@@ -0,0 +1,36 @@
---
name: pipeline
kind: function
lang: go
domain: core
version: "1.0.0"
purity: pure
signature: "func Pipeline[T any](fns ...func(T) T) func(T) T"
description: "Compone funciones T -> T en secuencia de izquierda a derecha. Pipeline(f, g, h)(x) equivale a h(g(f(x))). Sin funciones retorna la identidad."
tags: [pipeline, compose, functional, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/pipeline.go"
---
## Ejemplo
```go
transform := Pipeline(
func(s string) string { return strings.TrimSpace(s) },
func(s string) string { return strings.ToUpper(s) },
func(s string) string { return "[" + s + "]" },
)
transform(" hello ") // "[HELLO]"
```
## Notas
Funcion pura generica. Las funciones se aplican en orden de izquierda a derecha (no es composicion matematica tradicional). Si se pasa un slice vacio de funciones, la funcion retornada actua como identidad.
+31
View File
@@ -0,0 +1,31 @@
package core
import (
"fmt"
"time"
)
// RetryWithBackoff retries fn up to maxRetries times with exponential backoff.
// The delay between attempt i and i+1 is baseDelay * 2^i.
// Returns the first successful result or the last error after all retries are exhausted.
func RetryWithBackoff[T any](fn func() (T, error), maxRetries int, baseDelay time.Duration) (T, error) {
var zero T
if maxRetries < 0 {
return zero, fmt.Errorf("maxRetries must be >= 0, got %d", maxRetries)
}
var lastErr error
for attempt := 0; attempt <= maxRetries; attempt++ {
result, err := fn()
if err == nil {
return result, nil
}
lastErr = err
if attempt < maxRetries {
delay := baseDelay * (1 << uint(attempt))
time.Sleep(delay)
}
}
return zero, fmt.Errorf("all %d retries exhausted: %w", maxRetries+1, lastErr)
}
+40
View File
@@ -0,0 +1,40 @@
---
name: retry_with_backoff
kind: function
lang: go
domain: core
version: "1.0.0"
purity: impure
signature: "func RetryWithBackoff[T any](fn func() (T, error), maxRetries int, baseDelay time.Duration) (T, error)"
description: "Reintenta una funcion impura con backoff exponencial. El delay entre intento i e i+1 es baseDelay * 2^i. Retorna el primer resultado exitoso o el ultimo error tras agotar los reintentos."
tags: [retry, backoff, resilience, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/core/retry_with_backoff.go"
---
## Ejemplo
```go
result, err := RetryWithBackoff(func() (string, error) {
resp, err := http.Get("https://api.example.com/data")
if err != nil {
return "", err
}
defer resp.Body.Close()
return "ok", nil
}, 3, 100*time.Millisecond)
// Intenta hasta 4 veces (1 inicial + 3 reintentos)
// Delays: 100ms, 200ms, 400ms
```
## Notas
Funcion impura generica que usa time.Sleep para el backoff. El numero total de intentos es maxRetries + 1 (el intento inicial mas los reintentos). Si maxRetries es negativo retorna error inmediatamente.
@@ -0,0 +1,33 @@
package cybersecurity
import (
"regexp"
"strings"
)
var sqliPatterns = []struct {
name string
re *regexp.Regexp
}{
{"union_select", regexp.MustCompile(`(?i)\bunion\s+(all\s+)?select\b`)},
{"or_1_eq_1", regexp.MustCompile(`(?i)\bor\s+1\s*=\s*1`)},
{"comment_injection", regexp.MustCompile(`(--|#|/\*)\s*$`)},
{"single_quote_or", regexp.MustCompile(`(?i)'\s*(or|and)\s+'`)},
{"drop_table", regexp.MustCompile(`(?i)\bdrop\s+(table|database)\b`)},
{"sleep_benchmark", regexp.MustCompile(`(?i)\b(sleep|benchmark)\s*\(`)},
{"exec_xp", regexp.MustCompile(`(?i)\b(exec|xp_)\w*`)},
{"tautology", regexp.MustCompile(`(?i)\bor\s+['"]?\w+['"]?\s*=\s*['"]?\w+['"]?`)},
{"stacked_query", regexp.MustCompile(`;\s*(select|insert|update|delete|drop|alter)\b`)},
}
// DetectSQLInjection analiza un input en busca de patrones heuristicos de inyeccion SQL.
// Devuelve si se detecto una amenaza y el nombre del patron encontrado.
func DetectSQLInjection(input string) (isThreat bool, pattern string) {
normalized := strings.TrimSpace(input)
for _, p := range sqliPatterns {
if p.re.MatchString(normalized) {
return true, p.name
}
}
return false, ""
}
@@ -0,0 +1,21 @@
---
name: detect_sql_injection
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func DetectSQLInjection(input string) (isThreat bool, pattern string)"
description: "Analiza un input en busca de patrones heuristicos de inyeccion SQL y devuelve si se detecto amenaza y el patron encontrado."
tags: [cybersecurity, sqli, detection, security]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [regexp, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/detect_sql_injection.go"
---
@@ -0,0 +1,26 @@
package cybersecurity
import "math"
// EntropyShannon calcula la entropia de Shannon de los datos proporcionados.
// Devuelve un valor entre 0 (datos uniformes) y 8 (datos completamente aleatorios para bytes).
func EntropyShannon(data []byte) float64 {
if len(data) == 0 {
return 0
}
var freq [256]float64
for _, b := range data {
freq[b]++
}
n := float64(len(data))
entropy := 0.0
for _, f := range freq {
if f > 0 {
p := f / n
entropy -= p * math.Log2(p)
}
}
return entropy
}
@@ -0,0 +1,21 @@
---
name: entropy_shannon
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func EntropyShannon(data []byte) float64"
description: "Calcula la entropia de Shannon de un slice de bytes. Retorna un valor entre 0 y 8 bits por byte."
tags: [cybersecurity, entropy, shannon, analysis]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/entropy_shannon.go"
---
+14
View File
@@ -0,0 +1,14 @@
package cybersecurity
import "regexp"
var urlRegex = regexp.MustCompile(`https?://[^\s<>"'` + "`" + `\)\]\}]+`)
// ExtractURLs extrae todas las URLs (http/https) encontradas en el texto proporcionado.
func ExtractURLs(text string) []string {
matches := urlRegex.FindAllString(text, -1)
if matches == nil {
return []string{}
}
return matches
}
+21
View File
@@ -0,0 +1,21 @@
---
name: extract_urls
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func ExtractURLs(text string) []string"
description: "Extrae todas las URLs HTTP/HTTPS de un texto usando expresiones regulares."
tags: [cybersecurity, extract, url, parse]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [regexp]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/extract_urls.go"
---
@@ -0,0 +1,27 @@
package cybersecurity
import (
"fmt"
"net/http"
"time"
)
// FetchHTTPHeaders realiza una solicitud HTTP HEAD a la URL y devuelve los headers de respuesta.
func FetchHTTPHeaders(url string) (map[string][]string, error) {
client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Head(url)
if err != nil {
return nil, fmt.Errorf("error realizando solicitud HEAD a %s: %w", url, err)
}
defer resp.Body.Close()
headers := make(map[string][]string, len(resp.Header))
for k, v := range resp.Header {
headers[k] = v
}
return headers, nil
}
@@ -0,0 +1,21 @@
---
name: fetch_http_headers
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func FetchHTTPHeaders(url string) (map[string][]string, error)"
description: "Realiza una solicitud HTTP HEAD a una URL y devuelve los headers de la respuesta."
tags: [cybersecurity, io, http, headers]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net/http, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/fetch_http_headers.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import (
"crypto/md5"
"encoding/hex"
)
// HashMD5 calcula el hash MD5 de los datos proporcionados y devuelve el resultado como string hexadecimal.
func HashMD5(data []byte) string {
h := md5.Sum(data)
return hex.EncodeToString(h[:])
}
+21
View File
@@ -0,0 +1,21 @@
---
name: hash_md5
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func HashMD5(data []byte) string"
description: "Calcula el hash MD5 de un slice de bytes y devuelve el resultado como string hexadecimal."
tags: [cybersecurity, hash, md5, crypto]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [crypto/md5, encoding/hex]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/hash_md5.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import (
"crypto/sha256"
"encoding/hex"
)
// HashSHA256 calcula el hash SHA-256 de los datos proporcionados y devuelve el resultado como string hexadecimal.
func HashSHA256(data []byte) string {
h := sha256.Sum256(data)
return hex.EncodeToString(h[:])
}
+21
View File
@@ -0,0 +1,21 @@
---
name: hash_sha256
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func HashSHA256(data []byte) string"
description: "Calcula el hash SHA-256 de un slice de bytes y devuelve el resultado como string hexadecimal."
tags: [cybersecurity, hash, sha256, crypto]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [crypto/sha256, encoding/hex]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/hash_sha256.go"
---
+16
View File
@@ -0,0 +1,16 @@
package cybersecurity
import "net"
// IPInRange verifica si una direccion IP esta dentro de un rango CIDR dado.
func IPInRange(ip, cidr string) bool {
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
return false
}
_, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return false
}
return ipNet.Contains(parsedIP)
}
+21
View File
@@ -0,0 +1,21 @@
---
name: ip_in_range
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IPInRange(ip, cidr string) bool"
description: "Verifica si una direccion IP se encuentra dentro de un rango CIDR dado."
tags: [cybersecurity, network, cidr, check]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/ip_in_range.go"
---
+12
View File
@@ -0,0 +1,12 @@
package cybersecurity
import "encoding/base64"
// IsBase64 verifica si el string proporcionado es una cadena base64 valida (standard encoding).
func IsBase64(s string) bool {
if len(s) == 0 {
return false
}
_, err := base64.StdEncoding.DecodeString(s)
return err == nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: is_base64
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IsBase64(s string) bool"
description: "Valida si un string es una cadena base64 valida segun el encoding estandar."
tags: [cybersecurity, validation, base64, format]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [encoding/base64]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/is_base64.go"
---
+15
View File
@@ -0,0 +1,15 @@
package cybersecurity
// IsHex verifica si el string proporcionado es una cadena hexadecimal valida.
// Requiere longitud par y que todos los caracteres sean digitos hex (0-9, a-f, A-F).
func IsHex(s string) bool {
if len(s) == 0 || len(s)%2 != 0 {
return false
}
for _, c := range s {
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
return false
}
}
return true
}
+21
View File
@@ -0,0 +1,21 @@
---
name: is_hex
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func IsHex(s string) bool"
description: "Valida si un string es una cadena hexadecimal valida (longitud par, caracteres 0-9 a-f A-F)."
tags: [cybersecurity, validation, hex, format]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/is_hex.go"
---
@@ -0,0 +1,37 @@
package cybersecurity
// JaccardSimilarity calcula la similitud de Jaccard entre dos conjuntos de tokens.
// Devuelve un valor entre 0.0 (sin interseccion) y 1.0 (conjuntos identicos).
func JaccardSimilarity(a, b []string) float64 {
if len(a) == 0 && len(b) == 0 {
return 1.0
}
if len(a) == 0 || len(b) == 0 {
return 0.0
}
setA := make(map[string]struct{}, len(a))
for _, s := range a {
setA[s] = struct{}{}
}
setB := make(map[string]struct{}, len(b))
for _, s := range b {
setB[s] = struct{}{}
}
intersection := 0
for k := range setA {
if _, ok := setB[k]; ok {
intersection++
}
}
// Union = |A| + |B| - |A intersect B| (usando conjuntos sin duplicados)
union := len(setA) + len(setB) - intersection
if union == 0 {
return 0.0
}
return float64(intersection) / float64(union)
}
@@ -0,0 +1,21 @@
---
name: jaccard_similarity
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func JaccardSimilarity(a, b []string) float64"
description: "Calcula la similitud de Jaccard entre dos conjuntos de tokens. Retorna un valor entre 0.0 y 1.0."
tags: [cybersecurity, similarity, jaccard, tokens]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/jaccard_similarity.go"
---
@@ -0,0 +1,49 @@
package cybersecurity
// LevenshteinDistance calcula la distancia de edicion (Levenshtein) entre dos strings.
func LevenshteinDistance(a, b string) int {
ra := []rune(a)
rb := []rune(b)
la := len(ra)
lb := len(rb)
if la == 0 {
return lb
}
if lb == 0 {
return la
}
// Usar solo dos filas para optimizar memoria
prev := make([]int, lb+1)
curr := make([]int, lb+1)
for j := 0; j <= lb; j++ {
prev[j] = j
}
for i := 1; i <= la; i++ {
curr[0] = i
for j := 1; j <= lb; j++ {
cost := 1
if ra[i-1] == rb[j-1] {
cost = 0
}
del := prev[j] + 1
ins := curr[j-1] + 1
sub := prev[j-1] + cost
m := del
if ins < m {
m = ins
}
if sub < m {
m = sub
}
curr[j] = m
}
prev, curr = curr, prev
}
return prev[lb]
}
@@ -0,0 +1,21 @@
---
name: levenshtein_distance
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func LevenshteinDistance(a, b string) int"
description: "Calcula la distancia de edicion de Levenshtein entre dos strings. Util para deteccion de typosquatting."
tags: [cybersecurity, string, distance, typosquatting]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/levenshtein_distance.go"
---
+33
View File
@@ -0,0 +1,33 @@
package cybersecurity
import (
"fmt"
"io"
"net"
"strings"
"time"
)
// LookupWhois realiza una consulta WHOIS para el dominio proporcionado conectandose al servidor whois.iana.org.
func LookupWhois(domain string) (string, error) {
conn, err := net.DialTimeout("tcp", "whois.iana.org:43", 10*time.Second)
if err != nil {
return "", fmt.Errorf("error conectando al servidor WHOIS: %w", err)
}
defer conn.Close()
_ = conn.SetDeadline(time.Now().Add(10 * time.Second))
_, err = fmt.Fprintf(conn, "%s\r\n", domain)
if err != nil {
return "", fmt.Errorf("error enviando consulta WHOIS: %w", err)
}
var sb strings.Builder
_, err = io.Copy(&sb, conn)
if err != nil {
return "", fmt.Errorf("error leyendo respuesta WHOIS: %w", err)
}
return sb.String(), nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: lookup_whois
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func LookupWhois(domain string) (string, error)"
description: "Realiza una consulta WHOIS para un dominio conectandose al servidor whois.iana.org por TCP."
tags: [cybersecurity, io, whois, recon]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, io, net, strings, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/lookup_whois.go"
---
+44
View File
@@ -0,0 +1,44 @@
package cybersecurity
import (
"net/url"
"strings"
)
// trackingParams lista de parametros de tracking comunes a eliminar.
var trackingParams = map[string]bool{
"utm_source": true,
"utm_medium": true,
"utm_campaign": true,
"utm_term": true,
"utm_content": true,
"fbclid": true,
"gclid": true,
"ref": true,
"mc_cid": true,
"mc_eid": true,
}
// NormalizeURL normaliza una URL: convierte el host a minusculas, elimina fragmentos
// y remueve parametros de tracking comunes.
func NormalizeURL(rawURL string) string {
u, err := url.Parse(rawURL)
if err != nil {
return rawURL
}
// Lowercase host
u.Host = strings.ToLower(u.Host)
// Eliminar fragmento
u.Fragment = ""
// Eliminar parametros de tracking
q := u.Query()
for param := range trackingParams {
q.Del(param)
}
u.RawQuery = q.Encode()
return u.String()
}
+21
View File
@@ -0,0 +1,21 @@
---
name: normalize_url
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func NormalizeURL(rawURL string) string"
description: "Normaliza una URL: convierte el host a minusculas, elimina fragmentos y remueve parametros de tracking comunes."
tags: [cybersecurity, url, normalize, sanitize]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [net/url, strings]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/normalize_url.go"
---
+44
View File
@@ -0,0 +1,44 @@
package cybersecurity
import (
"encoding/binary"
"fmt"
"net"
)
// ParseIPCIDR parsea una notacion CIDR y devuelve la direccion de red, broadcast, cantidad de hosts y error.
func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error) {
ip, ipNet, err := net.ParseCIDR(cidr)
if err != nil {
return "", "", 0, fmt.Errorf("CIDR invalido: %w", err)
}
// Solo soportamos IPv4
ip4 := ip.To4()
if ip4 == nil {
return "", "", 0, fmt.Errorf("solo se soporta IPv4")
}
mask := ipNet.Mask
networkIP := ipNet.IP.To4()
network = networkIP.String()
// Calcular broadcast
broadcastIP := make(net.IP, 4)
for i := 0; i < 4; i++ {
broadcastIP[i] = networkIP[i] | ^mask[i]
}
broadcast = broadcastIP.String()
// Calcular hosts usables
netInt := binary.BigEndian.Uint32(networkIP)
bcastInt := binary.BigEndian.Uint32(broadcastIP)
total := int(bcastInt - netInt + 1)
if total > 2 {
hosts = total - 2 // excluir network y broadcast
} else {
hosts = total // /31 o /32
}
return network, broadcast, hosts, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: parse_ip_cidr
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: pure
signature: "func ParseIPCIDR(cidr string) (network string, broadcast string, hosts int, err error)"
description: "Parsea una notacion CIDR IPv4 y devuelve la direccion de red, broadcast y cantidad de hosts usables."
tags: [cybersecurity, network, cidr, parse]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [encoding/binary, fmt, net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/parse_ip_cidr.go"
---
+15
View File
@@ -0,0 +1,15 @@
package cybersecurity
import (
"fmt"
"net"
)
// ResolveDNS resuelve un hostname a sus direcciones IP usando el resolver del sistema.
func ResolveDNS(host string) ([]string, error) {
ips, err := net.LookupHost(host)
if err != nil {
return nil, fmt.Errorf("error resolviendo DNS para %s: %w", host, err)
}
return ips, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: resolve_dns
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func ResolveDNS(host string) ([]string, error)"
description: "Resuelve un hostname a sus direcciones IP usando el resolver DNS del sistema."
tags: [cybersecurity, io, dns, resolve]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/resolve_dns.go"
---
+34
View File
@@ -0,0 +1,34 @@
package cybersecurity
import (
"fmt"
"net"
"time"
)
// ScanPortTCP intenta conectarse a un puerto TCP y devuelve el estado ("open", "closed", "filtered"),
// un banner si el puerto esta abierto, y un posible error.
func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error) {
address := fmt.Sprintf("%s:%d", host, port)
timeout := time.Duration(timeoutMs) * time.Millisecond
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
// Distinguir entre conexion rechazada (closed) y timeout (filtered)
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
return "filtered", "", nil
}
return "closed", "", nil
}
defer conn.Close()
// Intentar leer un banner con timeout corto
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
buf := make([]byte, 1024)
n, _ := conn.Read(buf)
if n > 0 {
banner = string(buf[:n])
}
return "open", banner, nil
}
+21
View File
@@ -0,0 +1,21 @@
---
name: scan_port_tcp
kind: function
lang: go
domain: cybersecurity
version: "1.0.0"
purity: impure
signature: "func ScanPortTCP(host string, port int, timeoutMs int) (status string, banner string, err error)"
description: "Escanea un puerto TCP en un host dado. Devuelve el estado (open/closed/filtered) y un banner si esta abierto."
tags: [cybersecurity, io, port, scan]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: [fmt, net, time]
tested: false
tests: []
test_file_path: ""
file_path: "functions/cybersecurity/scan_port_tcp.go"
---
+12
View File
@@ -0,0 +1,12 @@
package datascience
// Autocorrelation calcula la autocorrelación de data con el desfase (lag) dado.
// Usa la correlación de Pearson entre data[0:n-lag] y data[lag:n].
// Si lag es inválido, retorna 0.
func Autocorrelation(data []float64, lag int) float64 {
n := len(data)
if lag < 0 || lag >= n {
return 0
}
return Pearson(data[:n-lag], data[lag:])
}
+21
View File
@@ -0,0 +1,21 @@
---
name: autocorrelation
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Autocorrelation(data []float64, lag int) float64"
description: "Calcula la autocorrelación de una serie temporal con un desfase (lag) dado, usando correlación de Pearson."
tags: [datascience, statistics, autocorrelation, timeseries]
uses_functions: [pearson_go_datascience]
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/autocorrelation.go"
---
+17
View File
@@ -0,0 +1,17 @@
package datascience
// Clip recorta cada valor del slice para que quede dentro del rango [min, max].
func Clip(data []float64, min, max float64) []float64 {
result := make([]float64, len(data))
for i, v := range data {
switch {
case v < min:
result[i] = min
case v > max:
result[i] = max
default:
result[i] = v
}
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: clip
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Clip(data []float64, min, max float64) []float64"
description: "Recorta cada valor del slice para que quede dentro del rango [min, max]."
tags: [datascience, clamp, clip, range]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/clip.go"
---
+38
View File
@@ -0,0 +1,38 @@
package datascience
import "math"
// DetectOutliers devuelve un []bool donde true indica que el valor es un outlier
// según z-score. Un valor es outlier si |z-score| > threshold.
func DetectOutliers(data []float64, threshold float64) []bool {
n := len(data)
if n == 0 {
return []bool{}
}
var sum float64
for _, v := range data {
sum += v
}
mean := sum / float64(n)
var sqSum float64
for _, v := range data {
d := v - mean
sqSum += d * d
}
stddev := math.Sqrt(sqSum / float64(n))
result := make([]bool, n)
if stddev == 0 {
return result
}
for i, v := range data {
z := (v - mean) / stddev
if z < 0 {
z = -z
}
result[i] = z > threshold
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: detect_outliers
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func DetectOutliers(data []float64, threshold float64) []bool"
description: "Detecta outliers en un slice de float64 usando z-score. Devuelve true para valores cuyo |z-score| supera el umbral."
tags: [datascience, statistics, outlier, anomaly]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/detect_outliers.go"
---
@@ -0,0 +1,8 @@
package datascience
import "fmt"
// FetchDataFrame ejecuta una consulta SQL contra un DSN y retorna los resultados como slice de mapas.
func FetchDataFrame(dsn, query string) ([]map[string]any, error) {
return nil, fmt.Errorf("not implemented")
}
+21
View File
@@ -0,0 +1,21 @@
---
name: fetch_data_frame
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: impure
signature: "func FetchDataFrame(dsn, query string) ([]map[string]any, error)"
description: "Ejecuta una consulta SQL contra un DSN y retorna los resultados como slice de mapas columna-valor."
tags: [datascience, io, bigquery, fetch]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["fmt"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/fetch_data_frame.go"
---
+61
View File
@@ -0,0 +1,61 @@
package datascience
import (
"math"
"math/cmplx"
)
// FFT calcula la Fast Fourier Transform usando el algoritmo Cooley-Tukey radix-2.
// Si la longitud de data no es potencia de 2, se rellena con ceros (zero-padding).
func FFT(data []float64) []complex128 {
n := len(data)
if n == 0 {
return []complex128{}
}
// Calcular la siguiente potencia de 2.
size := nextPow2(n)
// Convertir a complex128 con zero-padding.
x := make([]complex128, size)
for i := 0; i < n; i++ {
x[i] = complex(data[i], 0)
}
fftRecursive(x)
return x
}
// nextPow2 retorna la menor potencia de 2 >= n.
func nextPow2(n int) int {
p := 1
for p < n {
p <<= 1
}
return p
}
// fftRecursive aplica Cooley-Tukey radix-2 DIT in-place.
func fftRecursive(x []complex128) {
n := len(x)
if n <= 1 {
return
}
// Separar pares e impares.
even := make([]complex128, n/2)
odd := make([]complex128, n/2)
for i := 0; i < n/2; i++ {
even[i] = x[2*i]
odd[i] = x[2*i+1]
}
fftRecursive(even)
fftRecursive(odd)
for k := 0; k < n/2; k++ {
t := cmplx.Rect(1, -2*math.Pi*float64(k)/float64(n)) * odd[k]
x[k] = even[k] + t
x[k+n/2] = even[k] - t
}
}
+21
View File
@@ -0,0 +1,21 @@
---
name: fft
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func FFT(data []float64) []complex128"
description: "Calcula la Transformada Rápida de Fourier (FFT) usando el algoritmo Cooley-Tukey radix-2. Aplica zero-padding si la longitud no es potencia de 2."
tags: [datascience, dsp, fft, fourier, frequency]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math", "math/cmplx"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/fft.go"
---
+11
View File
@@ -0,0 +1,11 @@
package datascience
// GroupBy agrupa los elementos de un slice según la clave devuelta por keyFn.
func GroupBy[T any, K comparable](xs []T, keyFn func(T) K) map[K][]T {
groups := make(map[K][]T)
for _, x := range xs {
k := keyFn(x)
groups[k] = append(groups[k], x)
}
return groups
}
+21
View File
@@ -0,0 +1,21 @@
---
name: group_by
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func GroupBy[T any, K comparable](xs []T, keyFn func(T) K) map[K][]T"
description: "Agrupa los elementos de un slice según una función clave, devolviendo un mapa de clave a slice de elementos."
tags: [datascience, group, aggregate, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/group_by.go"
---
+39
View File
@@ -0,0 +1,39 @@
package datascience
import "math"
// Histogram calcula las frecuencias de data distribuidas en la cantidad de buckets indicada.
// Retorna un slice de longitud buckets con el conteo de elementos por cada intervalo equiespaciado.
func Histogram(data []float64, buckets int) []int {
if buckets <= 0 || len(data) == 0 {
return make([]int, buckets)
}
minVal := math.Inf(1)
maxVal := math.Inf(-1)
for _, v := range data {
if v < minVal {
minVal = v
}
if v > maxVal {
maxVal = v
}
}
counts := make([]int, buckets)
rang := maxVal - minVal
if rang == 0 {
// Todos los valores son iguales; poner todo en el primer bucket.
counts[0] = len(data)
return counts
}
for _, v := range data {
idx := int(float64(buckets) * (v - minVal) / rang)
if idx >= buckets {
idx = buckets - 1
}
counts[idx]++
}
return counts
}
+21
View File
@@ -0,0 +1,21 @@
---
name: histogram
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Histogram(data []float64, buckets int) []int"
description: "Calcula las frecuencias de un slice de float64 distribuidas en un número dado de buckets equiespaciados."
tags: [datascience, statistics, histogram, frequency]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/histogram.go"
---
+18
View File
@@ -0,0 +1,18 @@
package datascience
import "math"
// Impute rellena valores NaN usando forward-fill.
// Cada NaN se reemplaza con el último valor válido (no NaN) anterior.
// Si el primer valor es NaN y no hay valor anterior, se mantiene como NaN.
func Impute(data []float64) []float64 {
result := make([]float64, len(data))
last := math.NaN()
for i, v := range data {
if !math.IsNaN(v) {
last = v
}
result[i] = last
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: impute
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Impute(data []float64) []float64"
description: "Rellena valores NaN en un slice de float64 usando forward-fill, reemplazando cada NaN con el último valor válido anterior."
tags: [datascience, impute, missing, fill]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/impute.go"
---
+8
View File
@@ -0,0 +1,8 @@
package datascience
import "fmt"
// LoadCSV carga un archivo CSV y lo retorna como slice de mapas (columna -> valor).
func LoadCSV(path string) ([]map[string]string, error) {
return nil, fmt.Errorf("not implemented")
}
+21
View File
@@ -0,0 +1,21 @@
---
name: load_csv
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: impure
signature: "func LoadCSV(path string) ([]map[string]string, error)"
description: "Carga un archivo CSV desde disco y lo retorna como slice de mapas columna-valor."
tags: [datascience, io, csv, load]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["fmt"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/load_csv.go"
---
+8
View File
@@ -0,0 +1,8 @@
package datascience
import "fmt"
// LoadParquet carga un archivo Parquet y lo retorna como slice de mapas.
func LoadParquet(path string) ([]map[string]any, error) {
return nil, fmt.Errorf("not implemented")
}
+21
View File
@@ -0,0 +1,21 @@
---
name: load_parquet
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: impure
signature: "func LoadParquet(path string) ([]map[string]any, error)"
description: "Carga un archivo Parquet desde disco y lo retorna como slice de mapas columna-valor."
tags: [datascience, io, parquet, load]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["fmt"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/load_parquet.go"
---
+33
View File
@@ -0,0 +1,33 @@
package datascience
import "math"
// MinMaxScale escala los valores al rango [0, 1] usando min-max normalización.
// Si min == max, retorna un slice de ceros.
func MinMaxScale(data []float64) []float64 {
n := len(data)
if n == 0 {
return []float64{}
}
minVal := math.Inf(1)
maxVal := math.Inf(-1)
for _, v := range data {
if v < minVal {
minVal = v
}
if v > maxVal {
maxVal = v
}
}
rang := maxVal - minVal
result := make([]float64, n)
if rang == 0 {
return result
}
for i, v := range data {
result[i] = (v - minVal) / rang
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: min_max_scale
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func MinMaxScale(data []float64) []float64"
description: "Escala los valores de un slice al rango [0, 1] usando normalización min-max."
tags: [datascience, statistics, normalize, scale]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/min_max_scale.go"
---
+39
View File
@@ -0,0 +1,39 @@
package datascience
import "math"
// Pearson calcula el coeficiente de correlación de Pearson entre dos slices.
// Si los slices tienen distinta longitud, usa la longitud mínima.
// Retorna 0 si alguna desviación estándar es 0.
func Pearson(xs, ys []float64) float64 {
n := len(xs)
if len(ys) < n {
n = len(ys)
}
if n == 0 {
return 0
}
var sumX, sumY float64
for i := 0; i < n; i++ {
sumX += xs[i]
sumY += ys[i]
}
meanX := sumX / float64(n)
meanY := sumY / float64(n)
var num, denomX, denomY float64
for i := 0; i < n; i++ {
dx := xs[i] - meanX
dy := ys[i] - meanY
num += dx * dy
denomX += dx * dx
denomY += dy * dy
}
denom := math.Sqrt(denomX * denomY)
if denom == 0 {
return 0
}
return num / denom
}
+21
View File
@@ -0,0 +1,21 @@
---
name: pearson
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Pearson(xs, ys []float64) float64"
description: "Calcula el coeficiente de correlación de Pearson entre dos slices de float64."
tags: [datascience, statistics, correlation, pearson]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/pearson.go"
---
+17
View File
@@ -0,0 +1,17 @@
package datascience
// RollingWindow genera ventanas deslizantes de tamaño size sobre el slice xs.
// Si size <= 0 o size > len(xs), retorna nil.
func RollingWindow[T any](xs []T, size int) [][]T {
n := len(xs)
if size <= 0 || size > n {
return nil
}
windows := make([][]T, 0, n-size+1)
for i := 0; i <= n-size; i++ {
w := make([]T, size)
copy(w, xs[i:i+size])
windows = append(windows, w)
}
return windows
}
+21
View File
@@ -0,0 +1,21 @@
---
name: rolling_window
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func RollingWindow[T any](xs []T, size int) [][]T"
description: "Genera ventanas deslizantes de tamaño fijo sobre un slice genérico."
tags: [datascience, window, rolling, sliding, generic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/rolling_window.go"
---
+35
View File
@@ -0,0 +1,35 @@
package datascience
import "math"
// Standardize aplica Z-score normalización a un slice de float64.
// Cada valor se transforma a (x - mean) / stddev.
// Si stddev es 0, retorna un slice de ceros.
func Standardize(data []float64) []float64 {
n := len(data)
if n == 0 {
return []float64{}
}
var sum float64
for _, v := range data {
sum += v
}
mean := sum / float64(n)
var sqSum float64
for _, v := range data {
d := v - mean
sqSum += d * d
}
stddev := math.Sqrt(sqSum / float64(n))
result := make([]float64, n)
if stddev == 0 {
return result
}
for i, v := range data {
result[i] = (v - mean) / stddev
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: standardize
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func Standardize(data []float64) []float64"
description: "Aplica Z-score normalización a un slice de float64, transformando cada valor a (x - media) / desviación estándar."
tags: [datascience, statistics, normalize, zscore]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: ["math"]
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/standardize.go"
---
+15
View File
@@ -0,0 +1,15 @@
package datascience
// ZipSlices combina dos slices de float64 en pares [2]float64.
// El resultado tiene longitud igual al menor de los dos slices.
func ZipSlices(as, bs []float64) [][2]float64 {
n := len(as)
if len(bs) < n {
n = len(bs)
}
result := make([][2]float64, n)
for i := 0; i < n; i++ {
result[i] = [2]float64{as[i], bs[i]}
}
return result
}
+21
View File
@@ -0,0 +1,21 @@
---
name: zip_slices
kind: function
lang: go
domain: datascience
version: "1.0.0"
purity: pure
signature: "func ZipSlices(as, bs []float64) [][2]float64"
description: "Combina dos slices de float64 en un slice de pares [2]float64, truncando al más corto."
tags: [datascience, zip, combine, pair]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/datascience/zip_slices.go"
---
View File
@@ -0,0 +1,25 @@
package finance
import "math"
// AnnualizedVolatility calcula la volatilidad anualizada a partir de una serie de retornos.
// periodsPerYear indica cuantos periodos hay en un anio (e.g. 252 para retornos diarios).
// Retorna stddev(returns) * sqrt(periodsPerYear).
func AnnualizedVolatility(returns []float64, periodsPerYear float64) float64 {
n := len(returns)
if n < 2 {
return 0
}
var sum float64
for _, r := range returns {
sum += r
}
mean := sum / float64(n)
var variance float64
for _, r := range returns {
diff := r - mean
variance += diff * diff
}
variance /= float64(n - 1)
return math.Sqrt(variance) * math.Sqrt(periodsPerYear)
}
@@ -0,0 +1,31 @@
---
name: annualized_volatility
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func AnnualizedVolatility(returns []float64, periodsPerYear float64) float64"
description: "Calcula la volatilidad anualizada a partir de una serie de retornos y la frecuencia de los periodos."
tags: [finance, volatility, risk, annualized]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/annualized_volatility.go"
---
# annualized_volatility
Calcula la volatilidad anualizada como `stddev(returns) * sqrt(periodsPerYear)`. Usa desviacion estandar muestral (n-1).
## Ejemplo
```go
vol := finance.AnnualizedVolatility([]float64{0.01, -0.02, 0.015, 0.005, -0.01}, 252)
```
+32
View File
@@ -0,0 +1,32 @@
package finance
import "math"
// BollingerBands calcula las bandas de Bollinger: upper, middle (SMA), lower.
// Los primeros period-1 elementos de cada slice son 0.
func BollingerBands(data []float64, period int, numStdDev float64) (upper, middle, lower []float64) {
n := len(data)
upper = make([]float64, n)
middle = make([]float64, n)
lower = make([]float64, n)
if period <= 0 || period > n {
return
}
for i := period - 1; i < n; i++ {
var sum float64
for j := i - period + 1; j <= i; j++ {
sum += data[j]
}
mean := sum / float64(period)
var variance float64
for j := i - period + 1; j <= i; j++ {
diff := data[j] - mean
variance += diff * diff
}
std := math.Sqrt(variance / float64(period))
middle[i] = mean
upper[i] = mean + numStdDev*std
lower[i] = mean - numStdDev*std
}
return
}
+34
View File
@@ -0,0 +1,34 @@
---
name: bollinger_bands
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func BollingerBands(data []float64, period int, numStdDev float64) (upper, middle, lower []float64)"
description: "Calcula las bandas de Bollinger (upper, middle, lower) para una serie de precios."
tags: [finance, indicator, bollinger, bands]
uses_functions: []
uses_types: [bollinger_result_go_finance]
returns: [bollinger_result_go_finance]
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/bollinger_bands.go"
---
# bollinger_bands
Calcula las bandas de Bollinger. La banda media es la SMA, y las bandas superior e inferior estan a `numStdDev` desviaciones estandar de la media. Usa desviacion estandar poblacional.
## Ejemplo
```go
upper, middle, lower := finance.BollingerBands(
[]float64{22, 24, 23, 25, 26, 28, 27, 29, 30, 28},
5, 2.0,
)
```
+23
View File
@@ -0,0 +1,23 @@
package finance
// EMA calcula la media movil exponencial de data con el periodo dado.
// El primer valor valido se inicializa con la SMA de los primeros period elementos.
// Los primeros period-1 elementos del resultado son 0.
func EMA(data []float64, period int) []float64 {
n := len(data)
result := make([]float64, n)
if period <= 0 || period > n {
return result
}
k := 2.0 / float64(period+1)
// Seed con SMA
var sum float64
for i := 0; i < period; i++ {
sum += data[i]
}
result[period-1] = sum / float64(period)
for i := period; i < n; i++ {
result[i] = data[i]*k + result[i-1]*(1-k)
}
return result
}
+33
View File
@@ -0,0 +1,33 @@
---
name: ema
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func EMA(data []float64, period int) []float64"
description: "Calcula la media movil exponencial (EMA) sobre una serie de datos con un periodo dado."
tags: [finance, indicator, ema, moving-average]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/ema.go"
---
# ema
Calcula la media movil exponencial (Exponential Moving Average). Se inicializa con la SMA de los primeros `period` elementos. El multiplicador es `2 / (period + 1)`.
## Ejemplo
```go
result := finance.EMA([]float64{10, 11, 12, 13, 14, 15}, 3)
// result[2] = SMA de los primeros 3 = 11.0
// result[3] en adelante usa suavizado exponencial
```
+9
View File
@@ -0,0 +1,9 @@
package finance
import "fmt"
// FetchOHLCV obtiene datos OHLCV de un exchange para un simbolo e intervalo dados.
// TODO: implementar conexion real al exchange.
func FetchOHLCV(symbol, interval string) ([][]float64, error) {
return nil, fmt.Errorf("not implemented: FetchOHLCV(%s, %s)", symbol, interval)
}
+31
View File
@@ -0,0 +1,31 @@
---
name: fetch_ohlcv
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: impure
signature: "func FetchOHLCV(symbol, interval string) ([][]float64, error)"
description: "Obtiene datos OHLCV de un exchange para un simbolo e intervalo dados."
tags: [finance, io, exchange, fetch]
uses_functions: []
uses_types: [ohlcv_go_finance]
returns: [ohlcv_go_finance]
returns_optional: false
error_type: "error_go_core"
imports: [fmt]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/fetch_ohlcv.go"
---
# fetch_ohlcv
Stub para obtener datos OHLCV de un exchange. Pendiente de implementacion.
## Ejemplo
```go
data, err := finance.FetchOHLCV("BTC/USDT", "1h")
```
@@ -0,0 +1,9 @@
package finance
import "fmt"
// LoadOHLCVFromDuckDB carga datos OHLCV ejecutando una query en una base DuckDB.
// TODO: implementar conexion real a DuckDB.
func LoadOHLCVFromDuckDB(dbPath, query string) ([][]float64, error) {
return nil, fmt.Errorf("not implemented: LoadOHLCVFromDuckDB(%s, %s)", dbPath, query)
}
@@ -0,0 +1,31 @@
---
name: load_ohlcv_from_duckdb
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: impure
signature: "func LoadOHLCVFromDuckDB(dbPath, query string) ([][]float64, error)"
description: "Carga datos OHLCV ejecutando una query SQL en una base de datos DuckDB."
tags: [finance, io, duckdb, load]
uses_functions: []
uses_types: [ohlcv_go_finance]
returns: [ohlcv_go_finance]
returns_optional: false
error_type: "error_go_core"
imports: [fmt]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/load_ohlcv_from_duckdb.go"
---
# load_ohlcv_from_duckdb
Stub para cargar datos OHLCV desde DuckDB. Pendiente de implementacion.
## Ejemplo
```go
data, err := finance.LoadOHLCVFromDuckDB("/data/market.duckdb", "SELECT * FROM ohlcv WHERE symbol='BTC'")
```
+12
View File
@@ -0,0 +1,12 @@
package finance
import "math"
// LogReturn calcula el retorno logaritmico entre dos precios.
// Retorna ln(priceEnd / priceStart). Si priceStart <= 0 o priceEnd <= 0, retorna 0.
func LogReturn(priceStart, priceEnd float64) float64 {
if priceStart <= 0 || priceEnd <= 0 {
return 0
}
return math.Log(priceEnd / priceStart)
}
+32
View File
@@ -0,0 +1,32 @@
---
name: log_return
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func LogReturn(priceStart, priceEnd float64) float64"
description: "Calcula el retorno logaritmico entre un precio inicial y un precio final."
tags: [finance, return, logarithmic, atomic]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/log_return.go"
---
# log_return
Calcula el retorno logaritmico: `ln(priceEnd / priceStart)`. Si alguno de los precios es <= 0, retorna 0.
## Ejemplo
```go
r := finance.LogReturn(100.0, 110.0)
// r ~ 0.09531 (aprox 9.53%)
```
+27
View File
@@ -0,0 +1,27 @@
package finance
// MaxDrawdown calcula el maximo drawdown de una serie de valores (e.g. equity curve).
// Retorna la magnitud del drawdown (valor positivo entre 0 y 1 como fraccion del pico),
// y los indices de inicio (pico) y fin (valle) del peor drawdown.
// Si la serie tiene menos de 2 elementos, retorna 0, 0, 0.
func MaxDrawdown(values []float64) (maxDD float64, start, end int) {
n := len(values)
if n < 2 {
return 0, 0, 0
}
peakIdx := 0
peak := values[0]
for i := 1; i < n; i++ {
if values[i] > peak {
peak = values[i]
peakIdx = i
}
dd := (peak - values[i]) / peak
if dd > maxDD {
maxDD = dd
start = peakIdx
end = i
}
}
return
}
+32
View File
@@ -0,0 +1,32 @@
---
name: max_drawdown
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func MaxDrawdown(values []float64) (maxDD float64, start, end int)"
description: "Calcula el maximo drawdown de una curva de equity, retornando la magnitud y los indices pico-valle."
tags: [finance, drawdown, risk, metric]
uses_functions: []
uses_types: [drawdown_result_go_finance]
returns: [drawdown_result_go_finance]
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/max_drawdown.go"
---
# max_drawdown
Calcula el maximo drawdown (caida maxima desde un pico hasta un valle) como fraccion del pico. Retorna la magnitud (0 a 1) y los indices de inicio y fin.
## Ejemplo
```go
dd, s, e := finance.MaxDrawdown([]float64{100, 120, 90, 110, 80})
// dd = (120-80)/120 = 0.3333, s = 1, e = 4
```
+17
View File
@@ -0,0 +1,17 @@
package finance
// NormalizeOHLCV ajusta slices de precios OHLCV multiplicando por un factor.
func NormalizeOHLCV(open, high, low, close []float64, factor float64) ([]float64, []float64, []float64, []float64) {
n := len(open)
nOpen := make([]float64, n)
nHigh := make([]float64, n)
nLow := make([]float64, n)
nClose := make([]float64, n)
for i := 0; i < n; i++ {
nOpen[i] = open[i] * factor
nHigh[i] = high[i] * factor
nLow[i] = low[i] * factor
nClose[i] = close[i] * factor
}
return nOpen, nHigh, nLow, nClose
}
+38
View File
@@ -0,0 +1,38 @@
---
name: normalize_ohlcv
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func NormalizeOHLCV(open, high, low, close []float64, factor float64) ([]float64, []float64, []float64, []float64)"
description: "Ajusta slices de precios OHLCV multiplicando cada valor por un factor dado."
tags: [finance, ohlcv, normalize, adjust]
uses_functions: []
uses_types: [ohlcv_go_finance]
returns: [ohlcv_go_finance]
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/normalize_ohlcv.go"
---
# normalize_ohlcv
Ajusta slices de precios OHLCV (open, high, low, close) multiplicando cada elemento por un factor escalar. Util para ajustes por splits, conversiones de divisa, o normalizacion de series.
## Ejemplo
```go
o, h, l, c := finance.NormalizeOHLCV(
[]float64{100, 200},
[]float64{110, 210},
[]float64{90, 190},
[]float64{105, 205},
2.0,
)
// o = [200, 400], h = [220, 420], l = [180, 380], c = [210, 410]
```
+47
View File
@@ -0,0 +1,47 @@
package finance
// RSI calcula el Relative Strength Index.
// Usa el metodo de suavizado de Wilder (EMA con alpha = 1/period).
// Los primeros period elementos del resultado son 0.
func RSI(data []float64, period int) []float64 {
n := len(data)
result := make([]float64, n)
if period <= 0 || n < period+1 {
return result
}
var gainSum, lossSum float64
for i := 1; i <= period; i++ {
change := data[i] - data[i-1]
if change > 0 {
gainSum += change
} else {
lossSum -= change
}
}
avgGain := gainSum / float64(period)
avgLoss := lossSum / float64(period)
if avgLoss == 0 {
result[period] = 100
} else {
rs := avgGain / avgLoss
result[period] = 100 - 100/(1+rs)
}
for i := period + 1; i < n; i++ {
change := data[i] - data[i-1]
var gain, loss float64
if change > 0 {
gain = change
} else {
loss = -change
}
avgGain = (avgGain*float64(period-1) + gain) / float64(period)
avgLoss = (avgLoss*float64(period-1) + loss) / float64(period)
if avgLoss == 0 {
result[i] = 100
} else {
rs := avgGain / avgLoss
result[i] = 100 - 100/(1+rs)
}
}
return result
}
+31
View File
@@ -0,0 +1,31 @@
---
name: rsi
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func RSI(data []float64, period int) []float64"
description: "Calcula el Relative Strength Index (RSI) usando suavizado de Wilder."
tags: [finance, indicator, rsi, momentum]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/rsi.go"
---
# rsi
Calcula el Relative Strength Index (RSI) con el metodo de suavizado de Wilder. Los primeros `period` elementos son 0. El RSI oscila entre 0 y 100.
## Ejemplo
```go
result := finance.RSI([]float64{44, 44.34, 44.09, 43.61, 44.33, 44.83, 45.10, 45.42, 45.84}, 5)
```
+29
View File
@@ -0,0 +1,29 @@
package finance
import "math"
// SharpeRatio calcula el ratio de Sharpe.
// riskFreeRate es la tasa libre de riesgo por periodo.
// periodsPerYear indica cuantos periodos hay en un anio (e.g. 252 para diario).
// Formula: (mean(returns) - riskFreeRate) / stddev(returns) * sqrt(periodsPerYear)
func SharpeRatio(returns []float64, riskFreeRate float64, periodsPerYear float64) float64 {
n := len(returns)
if n < 2 {
return 0
}
var sum float64
for _, r := range returns {
sum += r
}
mean := sum / float64(n)
var variance float64
for _, r := range returns {
diff := r - mean
variance += diff * diff
}
std := math.Sqrt(variance / float64(n-1))
if std == 0 {
return 0
}
return (mean - riskFreeRate) / std * math.Sqrt(periodsPerYear)
}
+31
View File
@@ -0,0 +1,31 @@
---
name: sharpe_ratio
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func SharpeRatio(returns []float64, riskFreeRate float64, periodsPerYear float64) float64"
description: "Calcula el ratio de Sharpe anualizado a partir de retornos, tasa libre de riesgo y frecuencia."
tags: [finance, sharpe, risk, ratio]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [math]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/sharpe_ratio.go"
---
# sharpe_ratio
Calcula el ratio de Sharpe: `(mean(returns) - riskFreeRate) / stddev(returns) * sqrt(periodsPerYear)`. Usa desviacion estandar muestral.
## Ejemplo
```go
sr := finance.SharpeRatio([]float64{0.01, 0.02, -0.005, 0.015, 0.008}, 0.0001, 252)
```
+22
View File
@@ -0,0 +1,22 @@
package finance
// SMA calcula la media movil simple de data con el periodo dado.
// Retorna un slice de longitud len(data) donde los primeros period-1
// elementos son 0 (sin datos suficientes).
func SMA(data []float64, period int) []float64 {
n := len(data)
result := make([]float64, n)
if period <= 0 || period > n {
return result
}
var sum float64
for i := 0; i < period; i++ {
sum += data[i]
}
result[period-1] = sum / float64(period)
for i := period; i < n; i++ {
sum += data[i] - data[i-period]
result[i] = sum / float64(period)
}
return result
}
+32
View File
@@ -0,0 +1,32 @@
---
name: sma
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: pure
signature: "func SMA(data []float64, period int) []float64"
description: "Calcula la media movil simple (SMA) sobre una serie de datos con un periodo dado."
tags: [finance, indicator, sma, moving-average]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/sma.go"
---
# sma
Calcula la media movil simple (Simple Moving Average). Los primeros `period-1` elementos del resultado son 0 ya que no hay datos suficientes para calcular la media.
## Ejemplo
```go
result := finance.SMA([]float64{1, 2, 3, 4, 5}, 3)
// result = [0, 0, 2, 3, 4]
```
+10
View File
@@ -0,0 +1,10 @@
package finance
import "fmt"
// StreamTicks abre un stream de ticks en tiempo real para un simbolo.
// Retorna un canal de [2]float64 donde [0] es precio y [1] es volumen.
// TODO: implementar conexion real via websocket.
func StreamTicks(symbol string) (<-chan [2]float64, error) {
return nil, fmt.Errorf("not implemented: StreamTicks(%s)", symbol)
}
+31
View File
@@ -0,0 +1,31 @@
---
name: stream_ticks
kind: function
lang: go
domain: finance
version: "1.0.0"
purity: impure
signature: "func StreamTicks(symbol string) (<-chan [2]float64, error)"
description: "Abre un stream de ticks en tiempo real para un simbolo via websocket."
tags: [finance, io, stream, realtime]
uses_functions: []
uses_types: [tick_go_finance]
returns: [tick_go_finance]
returns_optional: false
error_type: "error_go_core"
imports: [fmt]
tested: false
tests: []
test_file_path: ""
file_path: "functions/finance/stream_ticks.go"
---
# stream_ticks
Stub para abrir un stream de ticks en tiempo real. Pendiente de implementacion.
## Ejemplo
```go
ch, err := finance.StreamTicks("ETH/USDT")
```
+53
View File
@@ -0,0 +1,53 @@
package finance
// TickToOHLCV agrega datos de ticks en velas OHLCV segun un intervalo en segundos.
// prices, volumes y timestamps deben tener la misma longitud.
// timestamps son unix seconds. intervalSecs define el ancho de cada vela.
// Retorna slices de open, high, low, close, volume para cada vela generada.
func TickToOHLCV(prices, volumes []float64, timestamps []int64, intervalSecs int64) (open, high, low, close, vol []float64) {
n := len(prices)
if n == 0 || intervalSecs <= 0 {
return
}
bucketStart := timestamps[0] - (timestamps[0] % intervalSecs)
o := prices[0]
h := prices[0]
l := prices[0]
c := prices[0]
v := volumes[0]
for i := 1; i < n; i++ {
currentBucket := timestamps[i] - (timestamps[i] % intervalSecs)
if currentBucket != bucketStart {
// Cerrar la vela anterior
open = append(open, o)
high = append(high, h)
low = append(low, l)
close = append(close, c)
vol = append(vol, v)
// Nueva vela
bucketStart = currentBucket
o = prices[i]
h = prices[i]
l = prices[i]
c = prices[i]
v = volumes[i]
} else {
if prices[i] > h {
h = prices[i]
}
if prices[i] < l {
l = prices[i]
}
c = prices[i]
v += volumes[i]
}
}
// Cerrar ultima vela
open = append(open, o)
high = append(high, h)
low = append(low, l)
close = append(close, c)
vol = append(vol, v)
return
}

Some files were not shown because too many files have changed in this diff Show More