En este tutorial, profundizamos en la construcción de una tubería de análisis de datos avanzados utilizando Polaresuna biblioteca de marco de datos Lightning-Fast diseñada para un rendimiento y escalabilidad óptimos. Nuestro objetivo es demostrar cómo podemos utilizar la evaluación perezosa de los polares, las expresiones complejas, las funciones de las ventanas y la interfaz SQL para procesar los conjuntos de datos financieros a gran escala de manera eficiente. Comenzamos generando un conjunto de datos de series de tiempo financieras sintéticas y avanzaremos paso a paso a través de una tubería de extremo a extremo, desde la ingeniería de características y las estadísticas de rodadura hasta el análisis y clasificación multidimensional. En todo momento, demostramos cómo los polares nos capacitan a escribir transformaciones de datos expresivas y de rendimiento, todo mientras mantenemos un bajo uso de memoria y garantizando una ejecución rápida.
import polars as pl
import numpy as np
from datetime import datetime, timedelta
import io
try:
import polars as pl
except ImportError:
import subprocess
subprocess.run(["pip", "install", "polars"], check=True)
import polars as pl
print("🚀 Advanced Polars Analytics Pipeline")
print("=" * 50)
Comenzamos importando las bibliotecas esenciales, incluidos los polares para operaciones de marcos de datos de alto rendimiento y numpy para generar datos sintéticos. Para garantizar la compatibilidad, agregamos un paso de instalación de respaldo para polares en caso de que no esté instalado. Con la configuración lista, señalamos el inicio de nuestra tubería de análisis avanzado.
np.random.seed(42)
n_records = 100000
dates = [datetime(2020, 1, 1) + timedelta(days=i//100) for i in range(n_records)]
tickers = np.random.choice(['AAPL', 'GOOGL', 'MSFT', 'TSLA', 'AMZN'], n_records)
# Create complex synthetic dataset
data = {
'timestamp': dates,
'ticker': tickers,
'price': np.random.lognormal(4, 0.3, n_records),
'volume': np.random.exponential(1000000, n_records).astype(int),
'bid_ask_spread': np.random.exponential(0.01, n_records),
'market_cap': np.random.lognormal(25, 1, n_records),
'sector': np.random.choice(['Tech', 'Finance', 'Healthcare', 'Energy'], n_records)
}
print(f"📊 Generated {n_records:,} synthetic financial records")
Generamos un conjunto de datos financiero sintético rico con 100,000 registros que usan Numpy, simulando datos de acciones diarias para los principales tickers como AAPL y TSLA. Cada entrada incluye características clave del mercado como precio, volumen, spread de oferta, capitalización de mercado y sector. Esto proporciona una base realista para demostrar análisis de polares avanzados en un conjunto de datos de la serie temporal.
lf = pl.LazyFrame(data)
result = (
lf
.with_columns([
pl.col('timestamp').dt.year().alias('year'),
pl.col('timestamp').dt.month().alias('month'),
pl.col('timestamp').dt.weekday().alias('weekday'),
pl.col('timestamp').dt.quarter().alias('quarter')
])
.with_columns([
pl.col('price').rolling_mean(20).over('ticker').alias('sma_20'),
pl.col('price').rolling_std(20).over('ticker').alias('volatility_20'),
pl.col('price').ewm_mean(span=12).over('ticker').alias('ema_12'),
pl.col('price').diff().alias('price_diff'),
(pl.col('volume') * pl.col('price')).alias('dollar_volume')
])
.with_columns([
pl.col('price_diff').clip(0, None).rolling_mean(14).over('ticker').alias('rsi_up'),
pl.col('price_diff').abs().rolling_mean(14).over('ticker').alias('rsi_down'),
(pl.col('price') - pl.col('sma_20')).alias('bb_position')
])
.with_columns([
(100 - (100 / (1 + pl.col('rsi_up') / pl.col('rsi_down')))).alias('rsi')
])
.filter(
(pl.col('price') > 10) &
(pl.col('volume') > 100000) &
(pl.col('sma_20').is_not_null())
)
.group_by(['ticker', 'year', 'quarter'])
.agg([
pl.col('price').mean().alias('avg_price'),
pl.col('price').std().alias('price_volatility'),
pl.col('price').min().alias('min_price'),
pl.col('price').max().alias('max_price'),
pl.col('price').quantile(0.5).alias('median_price'),
pl.col('volume').sum().alias('total_volume'),
pl.col('dollar_volume').sum().alias('total_dollar_volume'),
pl.col('rsi').filter(pl.col('rsi').is_not_null()).mean().alias('avg_rsi'),
pl.col('volatility_20').mean().alias('avg_volatility'),
pl.col('bb_position').std().alias('bollinger_deviation'),
pl.len().alias('trading_days'),
pl.col('sector').n_unique().alias('sectors_count'),
(pl.col('price') > pl.col('sma_20')).mean().alias('above_sma_ratio'),
((pl.col('price').max() - pl.col('price').min()) / pl.col('price').min())
.alias('price_range_pct')
])
.with_columns([
pl.col('total_dollar_volume').rank(method='ordinal', descending=True).alias('volume_rank'),
pl.col('price_volatility').rank(method='ordinal', descending=True).alias('volatility_rank')
])
.filter(pl.col('trading_days') >= 10)
.sort(['ticker', 'year', 'quarter'])
)
Cargamos nuestro conjunto de datos sintético en un Polars LazyFrame para habilitar la ejecución diferida, lo que nos permite encadenar transformaciones complejas de manera eficiente. A partir de ahí, enriquecemos los datos con características basadas en el tiempo y aplicamos indicadores técnicos avanzados, como promedios móviles, RSI y bandas de Bollinger, utilizando funciones de ventana y rodantes. Luego realizamos agregaciones agrupadas por ticker, año y trimestre para extraer estadísticas e indicadores financieros clave. Finalmente, clasificamos los resultados en función del volumen y la volatilidad, filtramos segmentos con poco cotizado y clasificamos los datos para la exploración intuitiva, todo mientras aprovecha el potente motor de evaluación perezoso de los Polares a su máximo ventaja.
df = result.collect()
print(f"\n📈 Analysis Results: {df.height:,} aggregated records")
print("\nTop 10 High-Volume Quarters:")
print(df.sort('total_dollar_volume', descending=True).head(10).to_pandas())
print("\n🔍 Advanced Analytics:")
pivot_analysis = (
df.group_by('ticker')
.agg([
pl.col('avg_price').mean().alias('overall_avg_price'),
pl.col('price_volatility').mean().alias('overall_volatility'),
pl.col('total_dollar_volume').sum().alias('lifetime_volume'),
pl.col('above_sma_ratio').mean().alias('momentum_score'),
pl.col('price_range_pct').mean().alias('avg_range_pct')
])
.with_columns([
(pl.col('overall_avg_price') / pl.col('overall_volatility')).alias('risk_adj_score'),
(pl.col('momentum_score') * 0.4 +
pl.col('avg_range_pct') * 0.3 +
(pl.col('lifetime_volume') / pl.col('lifetime_volume').max()) * 0.3)
.alias('composite_score')
])
.sort('composite_score', descending=True)
)
print("\n🏆 Ticker Performance Ranking:")
print(pivot_analysis.to_pandas())
Una vez que se completa nuestra tubería perezosa, recopilamos los resultados en un marcado de datos e revisamos inmediatamente los 10 trimestres principales según el volumen total del dólar. Esto nos ayuda a identificar períodos de intensa actividad comercial. Luego llevamos nuestro análisis un paso más allá al agrupar los datos por ticker para calcular las ideas de nivel superior, como el volumen de negociación de por vida, la volatilidad promedio de los precios y una puntuación compuesta personalizada. Este resumen multidimensional nos ayuda a comparar acciones no solo por volumen crudo, sino también por impulso y rendimiento ajustado al riesgo, desbloqueando ideas más profundas sobre el comportamiento general de los ticker.
print("\n🔄 SQL Interface Demo:")
pl.Config.set_tbl_rows(5)
sql_result = pl.sql("""
SELECT
ticker,
AVG(avg_price) as mean_price,
STDDEV(price_volatility) as volatility_consistency,
SUM(total_dollar_volume) as total_volume,
COUNT(*) as quarters_tracked
FROM df
WHERE year >= 2021
GROUP BY ticker
ORDER BY total_volume DESC
""", eager=True)
print(sql_result)
print(f"\n⚡ Performance Metrics:")
print(f" • Lazy evaluation optimizations applied")
print(f" • {n_records:,} records processed efficiently")
print(f" • Memory-efficient columnar operations")
print(f" • Zero-copy operations where possible")
print(f"\n💾 Export Options:")
print(" • Parquet (high compression): df.write_parquet('data.parquet')")
print(" • Delta Lake: df.write_delta('delta_table')")
print(" • JSON streaming: df.write_ndjson('data.jsonl')")
print(" • Apache Arrow: df.to_arrow()")
print("\n✅ Advanced Polars pipeline completed successfully!")
print("🎯 Demonstrated: Lazy evaluation, complex expressions, window functions,")
print(" SQL interface, advanced aggregations, and high-performance analytics")
Envolvemos la tubería mostrando la elegante interfaz SQL de Polars, ejecutando una consulta agregada para analizar el rendimiento del ticker posterior a 2021 con una sintaxis SQL familiar. Esta capacidad híbrida nos permite combinar transformaciones de polares expresivos con consultas SQL declarativas sin problemas. Para resaltar su eficiencia, imprimimos métricas clave de rendimiento, enfatizando la evaluación perezosa, la eficiencia de la memoria y la ejecución de la copia cero. Finalmente, demostramos cuán fácilmente podemos exportar los resultados en varios formatos, como Parquet, Arrow y JSONL, lo que hace que esta tubería sea poderosa y lista para la producción. Con eso, completamos un flujo de trabajo de análisis de alto rendimiento y círculo completo utilizando polares.
En conclusión, hemos visto de primera mano cómo la API perezosa de los Polares puede optimizar flujos de trabajo de análisis complejos que de otro modo serían lentos en las herramientas tradicionales. Hemos desarrollado una cartera de análisis financiero integral, que abarca desde la ingestión de datos sin procesar hasta los indicadores de rodadura, las agregaciones agrupadas y la puntuación avanzada, todo ejecutado con velocidad de aroma. No solo eso, sino que también aprovechamos la poderosa interfaz SQL de Polars para ejecutar consultas familiares sin problemas a través de nuestros marcos de datos. Esta doble capacidad para escribir expresiones de estilo funcional y SQL hace que los polares sea una herramienta increíblemente flexible para cualquier científico de datos.
Mira el Papel. Todo el crédito por esta investigación va a los investigadores de este proyecto. Además, siéntete libre de seguirnos Gorjeo Y no olvides unirte a nuestro Subreddit de 100k+ ml y suscribirse a Nuestro boletín.
Sana Hassan, una pasante de consultoría en MarktechPost y estudiante de doble grado en IIT Madras, le apasiona aplicar tecnología e IA para abordar los desafíos del mundo real. Con un gran interés en resolver problemas prácticos, aporta una nueva perspectiva a la intersección de la IA y las soluciones de la vida real.