Series almacena un historial asociado a las velas. A veces quieres decidir qué valores recoge el programa, en qué orden y cuándo los elimina. Puedes usar un array para ello.

¿Qué almacena un array?

Un array se compone de elementos consecutivos. Cada elemento tiene un índice; el primero es cero.

Un array almacena elementos del mismo tipo. Puedes tener uno de números o uno de textos, pero no ponemos texto en un array numérico. El mismo tipo no significa el mismo valor: 100, 103 y 101 son números distintos dentro del mismo array.

Si introduces 100, 103 y 101 en ese orden, el elemento 0 es 100, el 1 es 103 y el 2 es 101. El índice identifica aquí una posición de almacenamiento. No significa automáticamente un valor de tantas velas antes.

close[1] es el cierre anterior. array.get(prices, 1) es el segundo elemento de prices. Su antigüedad depende de cómo hayas llenado el array.

El espacio de nombres array

array.new_float(0) crea un array numérico inicialmente vacío. El cero indica la cantidad inicial de elementos, no un precio inicial.

OperaciónFunción
array.push(prices, close)Añade un elemento al final
array.size(prices)Devuelve la cantidad de elementos
array.shift(prices)Elimina y devuelve el primero
array.get(prices, 0)Lee el primer elemento
array.avg(prices)Calcula la media de los números guardados

El índice de array.get debe señalar un elemento existente. En un array de tres elementos son válidos 0, 1 y 2; 3 ya no lo es.

Guarda cinco precios recientes

Crea recent_prices.py:

"""
@pyne edge
"""
from pynecore import Persistent
from pynecore.lib import array, close, color, plot, script, ta


@script.indicator("Recent Prices", overlay=True)
def main():
    prices: Persistent[list[float]] = array.new_float(0)
    array.push(prices, close)
    if array.size(prices) > 5:
        array.shift(prices)
    stored_average = array.avg(prices)
    full_average = ta.sma(close, 5)
    plot(stored_average, "Stored average", color=color.blue, linewidth=2)
    plot(full_average, "SMA 5", color=color.orange)

list[float] indica el tipo de un array de números. Persistent garantiza que siga existiendo en la siguiente vela. No repetimos su creación en cada vela.

Realizamos las operaciones con el espacio de nombres array. No hace falta importar una biblioteca general de Python ni escribir un literal de lista.

Ejecútalo con los datos de demostración. La línea azul representa la media de los precios recogidos. En la primera vela hay uno, en la segunda dos, después tres y cuatro. Desde la quinta se conservan cinco elementos.

El gráfico de recent_prices.py muestra en azul la media de los precios almacenados y en naranja la SMA de cinco.
Comparamos la media de nuestro array con la SMA calculada sobre una ventana completa de cinco elementos.

El orden de añadir y eliminar

En la sexta vela añadimos primero el sexto cierre. El array tiene entonces seis elementos. La condición if es verdadera y quitamos el primero, el más antiguo. Al calcular la media solo contiene los cinco cierres de las velas segunda a sexta.

El principio del array guarda el precio conservado más antiguo y el final el más reciente. Desde que hay cinco elementos, array.get(prices, 0) devuelve el precio de cuatro velas antes, no el actual.

Para leer el más reciente, el último índice es array.size(prices) - 1. La cantidad y el último índice difieren en uno porque la numeración empieza en cero.

Ventanas parciales y completas

Al principio las dos medias se comportan de forma distinta. La del array puede calcularse con los precios recogidos, aunque sean cuatro o menos. ta.sma(close, 5) solo da un valor con una ventana completa de cinco.

Desde la quinta vela promedian los mismos cinco cierres. A partir de ahí las líneas deben coincidir dentro de la precisión numérica.

Por eso una media con array no sustituye automáticamente a la media móvil incorporada. Debes definir cómo tratar la ventana inicial.

¿Por qué limitamos el tamaño?

Si en cada vela solo añades un elemento, el array crece con los datos. Al terminar guardaría todos los cierres procesados.

Aquí necesitamos los últimos cinco, así que eliminamos los anteriores. En el momento del cálculo hay como máximo cinco elementos. En una tarea real también debes decidir qué datos conservar y durante cuánto tiempo.

Pruébalo por tu cuenta

Modifica el programa para conservar tres precios. Ajusta también la SMA a tres. Después dibuja el elemento conservado más antiguo como una tercera línea.

Solución del ejercicio

La condición de eliminación:

if array.size(prices) > 3:
    array.shift(prices)

La media incorporada y la nueva línea:

full_average = ta.sma(close, 3)
oldest_price = array.get(prices, 0)
plot(oldest_price, "Oldest stored price", color=color.gray)

array.push ocurre antes de la lectura en cada vela, por lo que siempre hay al menos un elemento. Una vez alcanzados tres, el precio más antiguo corresponde a dos velas antes.

Escribe el contenido del array

Con tres elementos conservados en vez de cinco y los precios 100, 103, 101, 105, anota el contenido después de cada vela. En la cuarta debe contener 103, 101 y 105, en ese orden.