Mostrando entradas con la etiqueta algoritmos. Mostrar todas las entradas
Mostrando entradas con la etiqueta algoritmos. Mostrar todas las entradas

jueves, 19 de mayo de 2022

ordenamiento bubble sort, quicksort y sin implementar en java.

version en video.


 

ordenar es poner las cosas siguiendo un orden(que viva la redundancia) por ejemplo podemos ordenar un numero de mayor a menor (5,4,3,2,1) o de menor a mayor (1,2,3,4,5) y en programacion existen muchos metodos de ordenamiento siendo uno de los mas sencillos de implementar bubble sort.

Bubble Sort.

es un método de ordenamiento donde iterativa mente vamos por toda la lista de elementos comparando el valor actual con el anterior (y rotandolos cuando no estan en orden) esto se hace cuantas veces como se necesite hasta que ido por todo el arreglo sin tener que rotar nada (significando esto que ya esta en orden).

es un algoritmo muy sencillo y tambien muy ineficiente en promedio toma O(n*n)  *1

en java se puede implementar de la siguiente manera.


 public static void main(String args[]) {
      int[] array = {13, 14, 42, 54, 56, 38, 97, 24, 57};
      bubbleSort(array);
      printArray(array);
  }

  public static boolean printArray(int[] input) {
      if (input.length == 0) {
          return false;
      }
      for (int i = 0; i < input.length; i++) {
          System.out.println(" " + input[i]);
      }
      return true;
  }

  public static boolean bubbleSort(int[] input) {
      if (input.length < 2) return false;
      boolean isInOrder;
      do {
          isInOrder = true;
          for (int i = 1; i < input.length; i++) {
              if (input[i - 1] < input[i]) {
                  int temporal = input[i - 1];
                  input[i - 1] = input[i];
                  input[i] = temporal;
                  isInOrder = false;
              }
          }
      } while (!isInOrder);
      return true;
  }


otro algoritmo muy conocido y que es creo de los que mas se usa es 

 

Quick Sort 


quicksort(ordenamiento rápido) y gusta bastante por que:

  • es rápido en promedio toma O(nlogn)
  • toma menos tiempo si los registros estan parcialmente ordenados(es verda en muchos casos)
  • optimiza bien el uso de cache *3

yo para entender  este algoritmo tuve que ver este video donde se explica muy bien *3.

el algoritmo es mas o menos asi.

  • usted empieza con un array (posiblemente desordenado)
  • tiene un metodo para ordernarlo(quicksort) que recibe este array, un minimo que es 0 el inicio del array y el tamaño del array(el intervalo que va ordenar)
  • este metodo despues de revisar que el min sea menor que el maximo llama a otro metodo que se encarga de encontrar una "particion" y mientras lo hace organiza los mas pequeño que la particion a la izquierda y lo mas grandes a la derecha (ordena no todo sino simplemente lo mayor y menor que donde esta la particion)
  • luego teniendo el index de esa particion se vuelve a llamar el metodo inicial dos veces una del inicio a la particion, y otra de la particion(el index de la misma hasta el tamaño original)
  • esto se sigue repitiendo recursivamente hasta que se acaba organizando todo.

entrando mas en detalle en el metodo que hace la particion se encarga de lo siguiente.

  • setea una variable i con el inicio/minimo y una variable j con el maximo/final
  • determina un pivote o elemento en el array para comparar(al inicio o al final del array generamente por facilidad, pero tambien se puede en en cualquier punto.
  • empieza a aumentar el i mientras lo que se encuentre sea menor que el pivote(osea que ya esta organizado con respecto al pivote), y a disminuir j mientras lo que se encuentre sea mayor que el pivote(osea que ya esta organizado en relacion al pivote)
  • si i es menor que j, es decir encontraron uno mayor y uno menor donde no debian estar estos se intercambian.
  • esto se repite y al final el pivote se pone en el "medio"(cambiando la variable en la poscision del pivote y la j) de manera de que queden menores a la izquierda y mayores a derecha del mismo
  • se retorna j, ya que en la poscision de j esta el pivote solo queda organizar las otras dos mitades usandolo.

en java una forma de implementar quicksort seria la siguiente.


public class mainClass {

    public static void main(String[] args) {
        int[] input = {1, 10, 10, 8, 6, 10, 1};
        quickSort(input, 0, input.length);
        printArray(input);
    }

    public static boolean printArray(int[] input) {
        if (input.length == 0) return false;
        System.out.println("");
        for (int i = 0; i < input.length; i++) {
            System.out.print(input[i] + " ");
        }
        return true;
    }

    public static void quickSort(int[] input, int min, int max) {
        if (min < max) {
            int j = partition(input, min, max);

            quickSort(input, min, j);
            quickSort(input, j + 1, max);
        }
    }

    public static int partition(int[] input, int min, int max) {
        int i = min;
        int j = max;
        int pivot = input[min];

        while (i < j) {
            do {
                i++;
            } while (i < input.length && input[i] < pivot);
            do {
                j--;
            } while (input[j] > pivot);
            if (i < j) {
                switchTheVariables(input, i, j);
            }
        }
        switchTheVariables(input, min, j);
        return j;
    }

    public static void switchTheVariables(int[] input, int a, int b) {
        int temporal = input[a];
        input[a] = input[b];
        input[b] = temporal;
    }

}

 implementar quicksort o bubble sort tan literal es interesante como ejercisio pero creo que tiene mas sentido utilizar el ordenamiento que ofrece el lenguaje, para ordenar en java podemos hacerlo asi

 


import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;

public class runjava {
    public static void main(String []args){
        Integer[] arrayInt={1,3,2,1,5,3,1};
        Arrays.sort(arrayInt);
        printArray(arrayInt);

        List<Integer> listInt=new ArrayList<Integer>();
        listInt.add(1);
        listInt.add(3);
        listInt.add(2);
        listInt.add(1);
        listInt.add(5);
        Collections.sort(listInt);
        System.out.print(listInt);

    }

    public static <A> boolean printArray(A[] array){
        if(array.length==0) return false;
        for(int i=0;i< array.length;i++){
            System.out.print(" "+array[i]);
        }
        return true;
    }
}

y si tuvieramos que implementar basados en un criterio propio x(por ejemplo ordenar un arreglo de string que sabemos son entero) o usando un campo especifico de una clase, o cualquier logica que quisieramos podriamos crear un comparator para informarle a java como queremos que ordene y hacerlo asi.


 import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class runJava{
    public static void main(String[] args) {

        Comparator<String> customComparator = ((a, b) -> {
            Integer aInt = Integer.valueOf(a);
            Integer bInt = Integer.valueOf(b);
            return aInt > bInt ? 1 : aInt < bInt ? -1 : 0;
        });
        List<String> listInt = new ArrayList<String>();
        listInt.add("1");
        listInt.add("3");
        listInt.add("2");
        listInt.add("1");
        listInt.add("5");
        Collections.sort(listInt);
        System.out.print(listInt);

    }

}

 

Referencias.

1. bubble sort https://www.geeksforgeeks.org/bubble-sort/

2. quicksort explicacion. https://www.youtube.com/watch?v=7h1s2SojIRw

3. por que gusta quicksort https://cs.stackexchange.com/questions/3/why-is-quicksort-better-than-other-sorting-algorithms-in-practice 

4. https://www.opinionatedgeek.com/codecs/htmlencoder

martes, 4 de enero de 2022

Notacion big O

version en video:


 

La notación de big o es una forma de medir y comparar el tiempo de ejecución de algoritmos.
Esta notación se puede usar para comparar dos implementaciones de algoritmos y posiblemente escoger la implementación más rápida.
hay que ser cuidadoso con esto en proyectos más halla de ejercisios por que para mi sigue siendo más prioritario hacer un código más mantenible y fácil de entender que un código que sea más rápido o teóricamente mas rapido(en mi caso por ejemplo me gusta mucho la programación funcional y la inmutabilidad para entender el código como bloques funcionales que reciben una entrada y retornan la misma salida para misma entrada, otro tema).
con esta aclaración igual creo que en el libro cracking the coding interview de gayle dan un ejemplo analogía muy bueno para entender el impacto de big o. Imaginemos que tenemos que transferir un archivo a un amigo y tenemos dos opciones.
transferir el archivo por internet(mandándolo por ejemplo por un correo electrónico).
llevar el archivo físico en un avión(por ejemplo en un disco duro)

en el primer caso transfiriendo el archivo por internet, entre mas grande el archivo más tiempo nos va tomar transferirlo por tanto tenemos una relación lineal.
tiempo transferencia = tiempo para transferir cantida * tamaño archivo + tiempo inicial, esto en notación de big O lo podríamos representar como O(n) entre mas grande el archivo mas tiempo nos 

tomaría y esto aumenta linealmente.
para el caso 2 llevar el archivo en un avión sin importar que tan grande es el archivo(podrían ser terabytes) el avión va tardar lo mismo (o una constante) en big O representamos esto como O(1)




este ejemplo creo que es muy bueno para entender la relevancia de la notación big O que nos muestra las diferencias de ejecución para cantidades enormes de datos, por ejemplo en general podemos decir que O(1) es mejor que O(n) pero si queremos transferir un archivo pequeño seguramente no lo vayamos hacer por un avion.

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