Problema: en este momento, el software más conveniente y completo (en lo sucesivo denominado software) para la automatización de la negociación en el mercado de valores ruso es el conocido TSLAB .
A pesar de las indudables ventajas en la forma de un editor visual conveniente para escribir scripts de negociación, que le permite escribir robots incluso sin el conocimiento de los lenguajes de programación, hay una serie de inconvenientes que hacen que el uso de este software sea extremadamente poco rentable para mí. Y creo que no solo para mí, dado que el tamaño promedio de una cuenta en Mosbirz, por regla general, no supera los 500 mil rublos.
1. Costo: tarifa de suscripción de 4500 rublos por mes + alquiler de un servidor virtual (1000 rublos por mes)
Este costo fijo supone una carga muy pesada para el resultado financiero de mi operación. Por lo tanto, tener un tamaño de cuenta de 500 mil rublos y con la esperanza de obtener al menos un 20% anual, con los costos existentes que necesita para ganar alrededor del 32-35% para alcanzar la rentabilidad planificada.
2. Inestabilidad del trabajo: a pesar de que mis algoritmos funcionan principalmente con órdenes de mercado (tipo de órdenes, que supone una ejecución del 100%), mis posiciones a menudo se duplicaron o no se ejecutaron en absoluto.
Objetivo: escribir software para automatizar el comercio para minimizar los costos fijos con una interfaz conveniente para crear scripts de comercio que le permite escribir robots de comercio sin ningún conocimiento profundo en programación.
La arquitectura de todo el proyecto con las mejoras actuales y funcionales y planificadas se presenta en la figura a continuación.

El enlace más importante en el programa es, sin duda, el sitio web de Tradingview (en adelante, TV). Simplemente nos presenta una funcionalidad conveniente para escribir sus scripts comerciales debido al lenguaje incorporado Pine_Script.
El idioma, por cierto, no requiere conocimiento específico y básicamente se parece al paquete Easy Language del Metastock, y la disponibilidad de ayuda en línea en ruso hace que escribir el código sea lo más agradable posible.
Un ejemplo de una estrategia para romper el promedio móvil (literalmente en tres líneas de código):
mov_average=sma(close,x) strategy.entry("My Long Entry Id", strategy.long,when=close>mov_average) strategy.entry("My Short Entry Id", strategy.short,when=close<mov_average)
Ahora que tiene una interfaz conveniente para escribir scripts de negociación, queda por establecer el proceso de envío de aplicaciones desde la TV directamente al sistema de negociación (en mi caso, esto es Quik), o directamente al servidor del corredor. El único problema es que la TV no tiene una API abierta para implementar esta funcionalidad.
Al intentar resolver este problema, lo primero que se me ocurrió fue utilizar un complemento para probar WebSelenium y buscar en los localizadores de XPath para encontrar los elementos que necesitamos responsables de las señales de compra-venta.
Las señales mismas se muestran en la tabla y no debería haber ningún problema. Pero para buscar la señal extrema, la tabla requería desplazamiento, pero no pude encontrar el elemento de desplazamiento (vea la figura a continuación).

Por lo tanto, tuve que buscar otra solución.
Visualmente, las señales de TV se muestran en el elemento del lienzo. El color de la señal se puede cambiar si es necesario (por ejemplo, venta en rojo, compra en verde).
Los colores configurados en TV los configuramos en nuestra aplicación. La aplicación en sí está escrita en Java, la interfaz gráfica se implementa utilizando la biblioteca Swing
Además en el programa en sí, debemos seleccionar el área del lienzo (o solo el área escaneada), en la que buscaremos los colores de control.
La siguiente figura muestra el sitio web de tradingview con tres instrumentos seleccionados, el color de la señal de trading se establece para cada uno de ellos. Estos colores están duplicados en mi programa Parse_Signal.
.
Después de configurar el área de escaneo y configurar el tipo de instrumento que se comercializa (por cierto, la configuración del programa tarda 5 minutos y se guarda en un archivo con la extensión .txt). Luego, presione el botón "INICIAR" y el programa comenzará a funcionar.
Funciona en dos hilos.
1 primer hilo:
Escanea el área seleccionada (en este caso, lienzo).
Hacemos el escaneo clásicamente usando la funcionalidad de la clase Robot:
BufferedImage buf= robot.createScreenCapture(new Rectangle(selection.x, selection.y, selection.width, selection.height))
A continuación, divide el escaneo resultante en una matriz de píxeles:
int[] pixels = copyFromBufferedImage(buf);
Busca los colores de control de las señales comerciales en una matriz de píxeles. Buscar de izquierda a derecha. Es decir El color del píxel más a la derecha es relevante para el programa:
for(int i=0;i<pixels.length;i++ ) { if (pixels[i] == (buy.getBackground().getRGB() & 0xFFFFFF)) { position = 1;

Registra una transacción comercial (en un archivo con la extensión .tri) de acuerdo con la plantilla, según el color encontrado. Aquí, de hecho, todo es simple en el terminal comercial de Quik, es posible leer automáticamente las transacciones de un archivo. Es suficiente para nosotros registrarlos de acuerdo con un cierto patrón. Quik, cuando aparece una nueva entrada, envía una solicitud al servidor del corredor. El archivo se lee cada 500 ms. La información sobre las señales comerciales se puede enviar opcionalmente por correo, teléfono o al sistema comercial (se pueden seleccionar tres parámetros simultáneamente). 1 hilo funciona con una frecuencia de 500 ms.
if (position==1&&status!=1&&b1==1) { if(dialog.isSend_phone()==true) { new SMS().sendSms(dialog.getPhone(), "TS_1: "+ (String)dialog.cbFirst.getSelectedItem()+" "+price+" "+new Date(), "TEST-SMS", dialog.getLogin(), dialog.getPassword());} if(dialog.isSend_trade()==true){ tr.Order_Buy();} if(dialog.isSend_mail()==true){ test.sendSignal("BUY","TS_1: Buy in signal at price "+ (String)dialog.cbFirst.getSelectedItem()+" "+price+" "+new Date());} status = 1;} ...................... ......................
2 el flujo del programa lleva a cabo la solicitud del precio del instrumento comercializado analizando la página html del sitio Finam . Se utiliza el complemento JSOUP. Aquí, simplemente subo las páginas html y busco el código del instrumento comercial requerido (por ejemplo: Si, Sber, etc.).
public void run() { while (true) { Document doc = null; Document doc_2 = null; try { doc = Jsoup.connect("https://www.finam.ru/quotes/futures/moex/").get(); doc_2 = Jsoup.connect("https://www.finam.ru/profile/mosbirzha-fyuchersy/sbrf").get();} catch (IOException e) { e.printStackTrace(); continue;} StringBuffer buffer = new StringBuffer(doc.text()); StringBuffer buffer_2 = new StringBuffer(doc_2.text()); Map<String, String> map = new HashMap<>() try {map.put(elements[1], buffer.substring(buffer.indexOf("Si "), buffer.indexOf("Si ") + 8).split("Si ")[1]); map.put(elements[2], buffer.substring(buffer.indexOf("RTS "), buffer.indexOf("RTS ") + 10).split("RTS ")[1]); map.put(elements[3], buffer.substring(buffer.indexOf("LKOH "), buffer.indexOf("LKOH ") + 10).split("LKOH ")[1]); map.put(elements[4], buffer.substring(buffer.indexOf("BR "), buffer.indexOf("BR ") +8).split("BR ")[1]); map.put(elements[5], buffer.substring(buffer.indexOf("GAZP "), buffer.indexOf("GAZP ") + 10).split("GAZP ")[1]); map.put(elements[6], buffer.substring(buffer.indexOf("GOLD "), buffer.indexOf("GOLD ") + 11).split("GOLD ")[1]); map.put(elements[7], buffer.substring(buffer.indexOf("MOEX "), buffer.indexOf("MOEX ") + 10).split("MOEX ")[1]); map.put(elements[8], buffer.substring(buffer.indexOf("MIX "), buffer.indexOf("MIX ") + 10).split("MIX ")[1]); map.put(elements[9], "0"); map.put(elements[10], buffer_2.substring(buffer_2.indexOf(" "), buffer_2.indexOf(" ") + 23).split(" ")[2] + buffer_2.substring(buffer_2.indexOf(" "), buffer_2.indexOf(" ") + 23).split(" ")[3]);} catch (Exception e) { System.out.println(e); text.setText(" "); continue;} price = String.valueOf((int) Double.parseDouble(map.get((String)
Está claro que este es un enlace débil en el programa, ya que cualquier cambio en la página html arrojará una excepción. Por lo tanto, en el futuro se planea solicitar información de intercambio para solicitarla directamente a través de Quik, o directamente desde el servidor del corredor.
Para hacer esto, puede usar la biblioteca .dll lista para Quik en C #, pero como escribo en Java, en mi caso será más fácil implementar un script en lua (el lenguaje Quik incorporado), que registrará los precios de compra y venta en un archivo separado, que el programa Parse_Signal y luego leerá.
Cabe señalar que, de hecho, tenemos un grupo bastante voluminoso de TV + Parser + Quik. Y a pesar de la estabilidad de esta solución, en el futuro se planea enviar aplicaciones no a Quik, sino directamente al servidor del agente (por ejemplo, usando la interfaz Atlentis de Alora como una opción ). La biblioteca realmente se implementa nuevamente en C #, por lo que debe encontrar algo.
Este programa me permitió resolver las tareas iniciales que establecí para mí:
a saber, a veces para reducir los costos fijos.
El código del programa se publica en el dominio público.
Si alguien está listo para compartir sus ideas sobre cómo interactuar con la televisión, me alegrará ver esto en los comentarios.