Página 1 de 5

Random

Publicado: 16 Abr 2018 15:30
por Rafa7
Sres. foristas,



Veo que en ProRealTime no hay ninguna función Random.

Quisiera diseñar un indicador, que lo podría llamar Random, que retorne un número aleatorio entre cero y uno, con 2 decimales (por lo menos), vela por vela (o sea una sucesión de números aleatorios).
Veo que en ProRealTime no es posible trabajar con Arrays, lo cual es una dificultad añadida.

¿Sugerís alguna idea a explorar?

De momento pienso es elaborar un algoritmo usando la función CurrentTime (hora actual), como punto de partida.

Esta es una pregunta abierta, incluyendo los que no conocen ProrealTime, ya que con pseudocódigo todos nos podemos entender. Tened en cuenta que en ProrealTime no podemos trabajar con Arrays.



Saludos.

Re: Random

Publicado: 16 Abr 2018 17:46
por Wikmar
RNDunicos.xls
(77.5 KiB) Descargado 249 veces

Re: Random

Publicado: 16 Abr 2018 22:26
por Rafa7
Gracias Wikmar,



Fíjate que el Excel que has colgado usa Arrays,y, expresamente he comentado que en ProRealTime no existen los Arrays.

Entonces lo que busco es un algoritmo para implementarlo en ProRealTime y el algoritmo no debe de tener ni un solo array.

De momento pienso en algo parecido a esto:

Código: Seleccionar todo

random = 10000
Mientras random > 9999, hacer:
   hh = hora_actual
   mm = minuto_actual
   ss = segundo_actual
   random = ((ss + i) * 3600 + mm * 60 + hh) mod 10007
   i = i + 1
Fin-Mientras
retorna random / 10000

No está el código en lenguaje ProRealTime sino en pseudocódigo.

Este código se ejecutaría en cada vela (en la 1ª vela más antigua "i" sería 0 -ya que en ProRealTIme las variables se inicializan a 0 por defecto-, en la 2ª vela más antigua "i" sería 1, en la 3ª vela más antigua "i" sería 2, etc ...)

Elijo 10007 porque es, de los números primos mayores de 9999, el más pequeño de todos ellos, para obtener una distribución más homogénea.
Como al dividir por 10007 el resto puede ser mayor que 9999, lo que hago es ignorar dichos resultados.
Como puede ser que en un mismo segundo puede procesar varias velas el BackTesting, voy sumando 1 a los segundos para que hayan menos colisiones (de lo contrario, en varias velas el valor de random no sería modificado).
Si pasamos el tiempo a segundos, tendríamos que calcular hh * 3600 + mm * 60 + ss, pero para conseguir una distribución más uniforme le doy la vuelta: (ss + i) * 3600 + mm * 60 + hh.

Espero que me entendáis aunque me explique fatal.

No estoy seguro, le estoy dando vueltas, ...
Si esta forma no es correcta o hay alguna otra forma más sencilla, espero que lo comentéis.



Saludos.

Re: Random

Publicado: 17 Abr 2018 07:59
por cls
Hola Rafa,
en este link está el código fuente que Microsoft usa para la función Random en .NET:
https://referencesource.microsoft.com/# ... 10694e64ca

Si no tienes arrays no podrás aplicarlo directamente, pero puede darte alguna idea.

S2

Re: Random

Publicado: 17 Abr 2018 13:39
por Wikmar
cls escribió: 17 Abr 2018 07:59Si no tienes arrays no podrás aplicarlo directamente, pero puede darte alguna idea.
Con esa misma intención pasé yo el código de esas macros de Excel.

Re: Random

Publicado: 17 Abr 2018 16:48
por Rafa7
cls escribió: 17 Abr 2018 07:59 Hola Rafa,
en este link está el código fuente que Microsoft usa para la función Random en .NET:
https://referencesource.microsoft.com/# ... 10694e64ca

Si no tienes arrays no podrás aplicarlo directamente, pero puede darte alguna idea.

S2
Si, es cierto, que da ideas.
Gracias, cls.

Re: Random

Publicado: 17 Abr 2018 17:09
por Rafa7
Gracias a Wikmar y cls.


Le he estado dando vueltas al pseudocódigo que compartí, y veo un par de cosas con poco sentido:
1.- No tiene mucho sentido, en un BackTesting, llamar iterativamente al current time, ya que en un mismo segundo el backtesting procesará un montón de velas. Pero si es interesante el current time como semilla de la serie de números pseudoaleatorios.
2.- Los multiplicadores 3600 y 60 no está adecuadamente justificados.

Así que he vuelto a replantear el pseudocódigo:

Código: Seleccionar todo

Si primeravela = 0:
   hh = hora del sistema
   mm = minuto del sistema
   ss = segundo del sistema
   random = 10000
   primeravela = 1
Fin-si
Mientras random > 9999:
   random = (ss * 1440 + mm * 24 + hh) mod 10007
   Si ss < 59:
      ss = ss + 1
   si-no:
      ss = 0
      Si mm < 59:
         mm = mm + 1
      si-no:
         mm = 0
         Si hh < 23:
            hh = hh + 1
         si-no:
            hh = 0
         Fin-si
      Fin-si
   Fin-si
Fin-mientras
retornar random / 10000
Multiplico mm por 24 porque hh variará entre 0 y 23, o sea, adoptará 24 valores.
Multiplico ss por 1440 porque ss lo he de multiplicar por 60 ya que mm varia entre 0 y 59, o sea adoptará 59 valores, pero como mm es multiplicado por 24, también ss ha se ser multiplicado por 24, 60 * 24 = 1440.

Entonces lo que hago com hh, mm, y ss, es sumar un segundo en cada iteriación, como si hh, mm y ss, fueran el tiempo de un reloj. Cuando ss llega a 60 lo que hace es poner a 0 ss y sumar 1 minuto, etc ... Por ejemplo, si el reloj marca 23:59:59 y le sumamos un segundo, pasa a 00:00:00.



Saludos.

Re: Random

Publicado: 17 Abr 2018 17:18
por Rafa7
Otra idea:

Código: Seleccionar todo

Si primeravela = 0:
   hh = hora del sistema
   mm = minuto del sistema
   ss = segundo del sistema
   primeravela = 1
Fin-si
Si ss < 59:
   ss = ss + 1
si-no:
   ss = 0
   Si mm < 59:
      mm = mm + 1
   si-no:
      mm = 0
      Si hh < 23:
         hh = hh + 1
      si-no:
         hh = 0
      Fin-si
   Fin-si
Fin-si
retornar ((ss * 1440 + mm * 24 + hh) mod 10007) / 10007
Es un poco mas sencillo porque nos ahorramos un "Mientras".



Saludos.

Re: Random

Publicado: 17 Abr 2018 17:28
por Rafa7
En una web (https://www.prorealcode.com/topic/random-value/) hay el siguiente código:

Código: Seleccionar todo

once MyNumber=5
MyNumber=round(((((rsi[14]*rsi[8])*(high[mynumber]+medianprice))*((intradaybarindex/time))+days+(dayofweek+1)*month)-round((((rsi[14]*rsi[8])*(high[mynumber]+medianprice))*((intradaybarindex/time))+days+(dayofweek+1)*month)/10-0.49)*10)-0.4)
Pero no me convence porque el RSI no tiene una distribución uniforme ya que la probabilidad de que el RSI tenga valores valores cercanos al nivel central es mayor que la probabilidad de que el RSI tenga valores extremos.

Re: Random

Publicado: 17 Abr 2018 17:52
por Rafa7
Wikmar, el Excel que has compartido creo que usa una función VBA randomize, que ProRealTime no tiene.

cls, el código que me comparte es muy interesante, pero me cuesta comprenderlo.
Hay una cosa que me hace mucha gracia, la siguiente línea de código:

ii = (21*i)%55;

O sea ii = (21 * i) mod 55.

Me hace gracia, porque 21 y 55 son números de la serie de Fibonacci, y, precisamente, el número áureo, al que tiende la serie de Fibonacci, está considerado el número más irracional que existe según un teorema. Hummm ... ¿casualidad? ¿o Microsoft ha querido elegir expresamente números de Fibonacci para su algoritmo para que la distribución sea más uniforme?

Re: Random

Publicado: 17 Abr 2018 19:22
por cls
Rafa7 escribió: 17 Abr 2018 17:52 ¿o Microsoft ha querido elegir expresamente números de Fibonacci para su algoritmo para que la distribución sea más uniforme?
Realmente ese código no es de MS, está sacado del libro Numerical Recipes in C. Hay mucha bibliografía que trata el tema de generación de números aleatorios. En ese libro y en el The Art of Computer Programming vol.2 de Donald E.Knuth hay muchos ejemplos de rutinas y sobre todo en el de Knuth se profundiza bastante a nivel matemático. El problema es que con ProReal poco vas a poder hacer.

Saludos

Re: Random

Publicado: 17 Abr 2018 22:51
por Rafa7
cls escribió: 17 Abr 2018 19:22 El problema es que con ProReal poco vas a poder hacer.
Efectivamente, ProRealTime tiene muchas limitaciones.
No obstante, tal vez el último algoritmo que he compartido, tomando como semilla el current time, sea bueno.
Lo tengo que mirar.
Pero exploraré otras ideas que puedan superar las limitaciones.

Re: Random

Publicado: 18 Abr 2018 06:51
por Rafa7
Creo que es mejor hacerlo más sencillo.
Por ejemplo, usando como semilla ss * 1440 + mm * 24 + hh, siendo hh:mm:ss el tiempo actual.
X(0) = ss * 1440 + mm * 24 + hh
X(n+1) = (A * X(n) + B) mod M.
E Ignorando X(0).
Pero habría que decidir cuales son los valores de A, B y M, adecuados.
Y, para ello, hay una serie de condiciones que deben cumplir A, B y M.

Re: Random

Publicado: 18 Abr 2018 10:17
por X-Trader
Hola Rafa7, yo no me complicaría con los tiempos, prueba con este pseudocódigo:

Código: Seleccionar todo

var
   x  : real;
begin
  X := 0.1;
  Repeat
    X := 147 * X – Int(147 * X);
    showmessage(Floattostr(X * 10));
    X := X+ 0.1;
  until X > 100;
end;
Saludos,
X-Trader

Re: Random

Publicado: 18 Abr 2018 10:32
por Rafa7
Gracias, X-Trader,



Lo simple me gusta más.

Hay una cosa que no entiendo del pseudocódigo: se define una variable real "a", pero luego en el código no se utiliza la "a" para nada. O una de dos, o sobra la definición de "a" o en el código falta la "a" por error al teclear.
¿Qué me dices de la variable "a"?



Saludos.