miércoles, 15 de septiembre de 2021

Flyway, r2dbc y spring boot

realizacion en video: https://www.youtube.com/watch?v=lJE5tkSmUPk


Flyway es una herramienta para versionar los cambios en base de datos que sirve para parecido a lo que se hace con git mantener un historial de los cambios en la base de datos y aplicarlos con facilidad.

Para usar flyway con spring lo primero es crear una aplicación de spring para esto nos dirijimos a https://start.spring.io/ ya estando hay vamos a seleccionar un proyecto gradle, con kotlin, en la versión 2.5.4(al momento que hice el tutorial), le vamos a poner el nombre flywaydemo y el package com.example.flywaydemo(si esto cambia solo es cambiar en los ejemplos la ruta de los package), packaging war y versión de java 16.

Luego vamos a dar clic en ADD DEPENDENCIES y vamos a seleccionar las dependencias de Spring Reactive Web(para que podamos trabajar con programación reactiva, flux, monos etc), Spring Data R2DBC como driver reactivo para conectarnos a la base de datos,Flyway Migration y postgresql. tal como se muestra en la imagen

 



En la imagen me faltó agregar postgresql pero agregarlo también.

teniendo escogido todo esto vamos a descargar el proyecto base y abrirlos con nuestro editor favorito de java en mi caso intellij y vamos a crear un archivo docker-compose que nos permita subir la base de datos postgres en docker de manera fácil para esto vamos a crear un archivo en la carpeta del proyecto llamado docker-compose.yml que tenga el siguiente contenido.
version: '3'
services:
postgresdb:
image: postgres
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: admin
POSTGRES_DB: flywaydemo


y vamos a correr en la terminal

$docker-compose up -d

esto nos va correr postgres con los valores que tenemos en el archivo y lo va subir listo para usarlo

lo siguiente que vamos a hacer es crear una carpeta configuration dentro de src/main/kotlin/com/example/flywayDemo/configuration/ y dentro creamos un archivo FlywayConfig como clase de kotlin con el siguiente contenido
package com.example.flywayDemo.configuration

import org.flywaydb.core.Flyway
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class FlywayConfig(@Value("\${spring.flyway.url}")private val url: String,
@Value("\${spring.flyway.user}")private val user: String,
@Value("\${spring.flyway.password}")private val password: String,
) {
@Bean(initMethod = "migrate")
fun flyway(): Flyway? = Flyway(Flyway.configure().baselineOnMigrate(true).dataSource(url, user, password))
}


esta clase es para que flyway interactue correctamente con r2dbc y fue sacada de aca https://stackoverflow.com/questions/59553647/how-to-run-flyway-migration-for-reactive-r2dbc-driver-on-sprintboot-stratup

luego entonces vamos a crear un archivo src/main/resources con el nombre application.yml donde vamos a poner la configuracion de nuestra aplicación tanto de flyway como de la conexion a postgres colocando el siguiente contenido
logging:
level:
root: INFO
spring:
r2dbc:
url: 'r2dbc:postgresql://localhost:5432/flywaydemo'
username: 'postgres'
password: 'admin'
pool:
validation-query: 'SELECT 1'

flyway:
url: 'jdbc:postgresql://localhost:5432/flywaydemo'
user: 'postgres'
password: 'admin'
schemas: 'public'
baseline-on-migrate: true


Teniendo esto listo vamos a crear una tabla de prueba para que flyway la cree en la base de datos dentro de la carpeta src/main/resources/db/migration un archivo llamado V20210915082200__init.sql en este caso estamos siguiendo el formato para nombrar el archivo de AÑO MES DIA HORA_MILITAR MINUTO SEGUNDO dos guión bajo <cualquier nombre> . sql, la idea es que con esto podemos saber cuando se hizo cada cambio con la fecha y que flyway pueda ordenar la aplicación de los registros dentro de este archivo vamos a poner la creación de una tabla simple.
CREATE TABLE public.demouser
(
"id" BIGSERIAL PRIMARY KEY,
"username" text NOT NULL,
"password" text NOT NULL,
"created_at" timestamptz NOT NULL DEFAULT now(),
"last_updated_at" timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS demouser_userName_index ON public.demouser ("username");


en esta misma carpeta también vamos a colocar otro archivo llamado V20210915083000__registro.sql con el siguiente contenido
insert into public.demouser(username,password) values('sebastian','miclave')


teniendo esto listo ya no es sino correr la aplicación y conectarnos a la database que estamos corriendo con docker para revisar en este caso yo me voy a conectar usando DBeaver con las credenciales que se definieron en el archivo docker-compose

 


y correr un script como este

select * from public.demouser;

Con esto verificamos que flyway se encargó por nosotros de crear la tabla e insertar el registro, los cambios futuros en la base de datos se crean como archivos independientes respetando el formato y haciendo las modificaciones en la base de datos como haríamos en la consola de postgresql de esta manera mantenemos los cambios versionados.

Solo una nota más si es posible recomiendo que los nombres de propiedades en la tabla no tengan mayúsculas para evitar problemas tengo entendido que tambien tiene solucion pero entra en juego otra configuracion para el formatter

viernes, 27 de agosto de 2021

Sobre Spring Boot y Java

 Para mi Spring boot llegó para ser una herramienta extremadamente útil para los desarrolladores especialmente de java pues confiere unas habilidades por defecto bastante comunes en aplicaciones de java, de una manera rápida y sin mucho rodeo.

He escuchado críticas a java primero por que no es tan práctico para la programación funcional y por que hay que escribir mucho código para lograr funcionalidades que en otros lenguajes se hacen en mucho menos espacio, sin esto dejar de ser cierto creo que java se sigue usando porque hay muchos programadores de java al menos aqui en latinoamerica, hay muchos sistemas legados de java y estas desventajas no muestran algo necesariamente mal con el lenguaje.

Spring cómo framework trajo un montón de soluciones listas para instalar en aplicaciones java, pero tenía dos cosas que se mejoraron enormemente con la traída en escena de spring boot. Spring boot funciona encima de spring como una manera de controlar automáticamente los archivos de configuración en spring(que podían llegar a ser extensos) con configuraciones por defecto cuando es posible,  y con el descubrimiento de clases.

La configuración automática permite que solo definamos la configuración de aquellas cosas que queremos cambiar y que el spring boot maneje el resto.
El descubrimiento de clases nos permite que spring controle el contexto de la aplicación de esta manera solo carga las clases que sean necesarias basado en anotaciones del tipo @ConditionalOn ….. , y usar anotaciones como  @autowired que nos permiten cargar interfaces/servicios/controladores en una clase dejando que spring boot resuelva cuál es la que se debe cargar y manteniendo el contexto de la aplicación general.

con spring boot el uso de anotaciones es común y práctico, por ejemplo si nosotros quisiéramos usar una caché en memoria para un método que hace un proceso pesado de procesamiento/memoria y/0 hace un llamado de red podemos en cuestión de dos anotaciones tenerla funcionando (un @EnabledCache en la configuración de spring y un @Cacheable en el método que queremos guarde en memoria sus resultados) lo que es ciertamente potente

Con estas y otras cosas spring boot genera velocidad en el desarrollo de aplicaciones java y/o kotlin(yo personalmente prefiero usarlo con kotlin por que me parece práctico en el manejo de valores nulos y la verbosidad de las aplicaciones).

las opiniones de java/kotlin son eso opiniones, sobre spring boot la fuente fue Spring Boot in Action de Craig Walls (capitulo 1 y 2)

martes, 10 de agosto de 2021

Trading algoritmico

Hay muchas maneras de hacer lo mismo con resultados distintos para invertir pasa lo mismo podemos invertir con estrategias comprobadas atravez del tiempo como en un portafolio altamente diversificado y a largo plazo, si se le da suficiente  tiempo y suficiente dinero se va terminar con riqueza inevitablemente como lo dice nick murray en su libro simple wealth, inevitable wealth.

pero el argumento contrario  tambien tiene algo de verdad si los mercados son eficientes, son eficientes por que los participantes del mismo así lo hacen.

bueno entonces las estrategias algorítmicas buscan encontrar patrones en los mercados para obtener ganancias por encima de las normales de los mismos, esto inevitablemente conlleva riesgos pues nada garantiza que por que algo sucedió antes vaya suceder después.

lo primero que necesitamos para esto es obtener la información del mercado una opción es usar la api de alpha avantage para usarla se debe obtener una clave o api-key atravez de su pagina web que dan gratuitamente luego de tenerla se puede usar este endpoint para consultar el simbolo de la empresa que queramos analizar colocandolo en keywords

https://www.alphavantage.co/query?function=SYMBOL_SEARCH&keywords=bmw&apikey=YOUR-API-KEY

 teniendo el simbolo luego vamos a este otro endpoint para obtener la informacion historica diaria del simbolo

https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=BMW.FRK&outputsize=full&apikey=YOUR-API-KEY

 Esta info luego puede ser organizada en un dataframe de python con el siguiente codigo

import numpy as np
import pandas as pd
import pandas_datareader.data as pdr
from datetime import datetime
import matplotlib.pyplot as plt
plt.style.use('seaborn')
import requests
import json
response = requests.get("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=BMW.FRK&outputsize=full&apikey=YOUR-API-KEY")
alphadict = json.loads(response.text)
alphadict.keys()
stock = pd.DataFrame(alphadict['Time Series (Daily)']).T
stock.columns = ['open', 'high', 'low', 'close','volume']
stock.index = pd.to_datetime(stock.index)
stock = stock.sort_index(ascending = True)
stock = stock.astype(float)
raw=stock[['close']].copy()
raw.columns=['close']
raw.tail()

 

  Con ese codigo quedamos en la variable raw con un dataframe que contiene los closing prices para la compañia bmw, que podemos usar directametne para generar modelos de trading algoritmico(tecnicos, cuantitativos, sumandole mas informacion para otros modelos).para verificar el simbolo yo encuentro especialmente util la siguiente linea

raw[-2000:].plot(lw=2.0,figsize=(10,6)

nos permite generar un grafico con los valores ir cambiando el -2000 por la cantida de registros que tengamos en nuestra herramienta de trading para mirar por encima que los valores coincidan con la grafica. 

luego con estos valores por ejemplo podemos probar alguna extrategia ahora mismo la unica que yo estoy probando es usar medias moviles, con fuerza bruta como indicador de momentum para una operacion que se abre el lunes y se cierra el viernes

from itertools import product
sma1 = range(0, 201, 5)
sma2 = range(200,501, 5)
results = pd.DataFrame()
for SMA1, SMA2 in product(sma1, sma2):
    data=raw.copy()
    data.dropna(inplace=True)
    data['Returns'] = np.log(data['close'] / data['close'].shift(4))
    data['SMA1'] = data['close'].rolling(SMA1).mean()
    data['SMA2'] = data['close'].rolling(SMA2).mean()
    data.dropna(inplace=True)
    data['Position'] = np.where(data['SMA1'] > data['SMA2'], 1, -1)
    data['Strategy'] = data['Position'].shift(4) * data['Returns']
    data['date']=data.index
    data['day-of-week']=data['date'].dt.day_name()
    data=data[data['day-of-week']=='Friday']
    data=data[-100:]
    data.dropna(inplace=True)
    perf = np.exp(data[['Returns', 'Strategy']].sum())
    results = results.append(pd.DataFrame({'SMA1': SMA1, 'SMA2': SMA2,'MARKET': perf['Returns'],
                                           'STRATEGY': perf['Strategy'],
                                           'OUT': perf['Strategy'] - perf['Returns']},index=[0]), ignore_index=True)

results.sort_values('OUT', ascending=False).head(7)


los rangos de la variable sma1 y sma2 pueden ser reducidos considerablemente para que no tome tanto tiempo la fuerza bruta y son los que usan para hacer la fuerza bruta, alfinal se compara lo que indique esta estrategia contra una de comprar y mantener la operacion y se organiza para obtener el que mayores ganancias reporte.

 esto termina siendo sobreajustado(overfitting) por que no tiene datos de prueba para evaluar aparte y ya de por si hacer esto es mineria de datos por lo que el nivel de riesgo es elevado de seguir una estrategia como esta creo es elevado, por tanto recomiendo no usarla  

notas del curso https://learning.oreilly.com/learning-paths/learning-path-hands-on/9781492082613/ - Learning Path: Hands-On Algorithmic Trading with Python de Deepak Kanungo

el segundo bloque de codigo de fuerza bruta esta modificado del codigo encontrado en el  capitulo 15 de Python for Finance, 2nd Edition, donde tambien explican otras estrategias, y dan mas detalle del mismo

jueves, 22 de julio de 2021

Microservicios

notas del libro Microservices Patterns,Chris Richardson, capítulo 1 y 2.


Lo primero es entender que existen varias dimensiones en la arquitectura de software, es decir un sistema puede estar usando varias arquitecturas al mismo tiempo por ejemplo una arquitectura de micro-servicios con arquitectura hexagonal, o una arquitectura monolítica con arquitectura de 3 capas.para explicar esto el autor usa las 4+1 vistas y un escenario y un sistema de coordenadas x,y,z para representar las diferentes dimensiones de la arquitectura.


una arquitectura de micro-servicios es una arquitectura en la que la aplicación está generada por múltiples servicios independientes y desacoplados(cuando se dice que los servicios deben ser desacoplados en una arquitectura de micro-servicios esto significa que los servicios deben comunicarse por api y que cada servicio debe tener su propia base de datos)


y una arquitectura monolítica es una arquitectura de aplicación con un solo desplegable/ejecutable.

la arquitectura de micro-servicios tiene como es usual ventajas y desventajas que el autor explica en 3 partes

  1. las fortalezas de la arquitectura o lo bueno que trae
  2. el contexto resultante o como queda el sistema después de aplicar la arquitectura con que debilidades y que fortalezas
  3. y los patrones relacionados como un diagrama en el que se relaciona que otro patrón podría reemplazar a esta/cubrir sus problemas/ mejorarlo/o si este patrón es mejora de otro.

Para él es claro que si una empresa startup está empezando es mejor que esta empieze con una arquitectura monolítica y luego realiza el refactor a un arquitectura de micro-servicios. 


en qué punto hacer ese refactor es una línea delgada pero hay indicadores para reconocerlo por ejemplo.

  • si el equipo de desarrolladores son muchos +7 seguramente tiene mas sentido dividir las responsabilidades, para con esto balancear el costo de la comunicación entre tantas personas es muy improductivo
  • si la base de código es muy compleja y no le cabe en la cabeza a una sola persona, seguramente implica que no la deba trabajar una sola persona sino dividirla para diferentes partes las trabajen diferentes personas
  • cuando la cantidad de usuarios es muy alta y el escalamiento es muy complejo. por ejemplo por que una parte de la aplicación requiere mucha memoria por una in-memory database, otra tiene una red neuronal y requiere gpu etc. escalar es complejo porque cada instancia de la aplicación va requerir la suma de recursos que necesita la app como todo para correr

Incluso con estos indicadores mutar o irse del monolito a una arquitectura de micro-servicios es peligroso y puede salir mal en el peor de los casos se termina con un monolito distribuido un engendro que suma las desventajas del monolito y las desventajas de los micro-servicios. 


Al mismo tiempo y siendo complejo en cierto punto hace más sentido realizar micro-servicios porque la curva exponencial para realizar entregas en el monolito se vuelve insostenible, y muchas empresas que han escalado mucho muchísimo lo han podido hacer por las capacidades que les proporciona una arquitectura de micro-servicios.


el autor recomienda juntar micro-servicios con una arquitectura hexagonal(o de puertos y adaptadores) pues esta encaja bien con DDD( domain driven design) que al mismo tiempo encaja muy bien con la división de un servicio monolito en micro-servicios, en otras palabras un triángulo virtuoso.


y describe 3 pasos generales para cambiar de una arquitectura monolítica a una micro-servicios.


  1. reconocer los procesos que realiza la organización(estos se traducen usualmente a llamados o endpoint rest)
  2. Reconocer los servicios: a través de los procesos fundamentales de la organización oa través de subdominios identificados por DDD.
  3. identificar las api. es decir las interfaces de comunicación(de los servicios o atravesar de llamadas rest o eventos por mensajería)

yo creo que  plantear una arquitectura de micro-servicios es inevitable en cierto momento cuando las organizaciones crecen y su modelo de negocio tiene una base tecnología, y aunque tiene muchas complejidades lo único que queda es hacerlo lo mejor posible para no terminar solo con desventajas y/o más problemas