Package psconsole

Source Code of psconsole.TaskManager$ReciveOrderCheck

/*
* Neiro Technology 2011-2014
*/
package psconsole;

import java.awt.Color;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import psconsole.ServerConsole.Terminal;
import textsockets.PSPackage;

/**
* Менеджер задач. Содержит список активных и исторических задач.
* Автоматом экспортирует всё в xml.
* @author deathNC
*/
public class TaskManager {

    public TaskManager(MainForm form) {
        this.form = form;
        taskList = new LinkedList<>();
        startThreads();
    }
   
    private void startThreads() {
        // -- запуск потока-менеджера исполнения задач
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        threadManagerTaskExecuting();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }
   
    /**
     * Нельзя вызывать данный метод! Он вызывается автоматически
     * потоком-менеджером задач
     */
    private void threadManagerTaskExecuting() throws Exception {
        Thread.sleep(200);
        int i = 0;
        int stat;
        long tm = form.timeCurrent;
        boolean needForRefresh = false;
        synchronized (taskList) {
            Iterator<Task> iter = taskList.iterator();
            while ( (64 > i++) && iter.hasNext()) {
                Task task = iter.next();
                // -- отправка задач на исполнение
               
                // -- по типу запуска определение, пора ли запускать
                stat = 0;
                if (task.startNow) {
                    // если с момента старта не прошло более 30 сек, отправляем
                    if (tm - task.timeStart > 30000) {
                        stat = 1;
                        if (task.status == TaskStatus.TS_Sending) {
                            task.status = TaskStatus.TS_Finished;
                            needForRefresh = true;
                        }
                    }
                } else {
                    // если за 60 секунд
                    if (task.timeStart - tm > 60000) stat = -1;
                    else if (task.timeStart - tm < 5000) stat = 1;
                }
               
                if (stat == 0) {
                    if (task.status != TaskStatus.TS_Sending)
                        needForRefresh = true;
                    task.status = TaskStatus.TS_Sending;
                } else if (stat < 0) {
                    if (task.status != TaskStatus.TS_Waiting)
                        needForRefresh = true;
                    task.status = TaskStatus.TS_Waiting;
                } else if (task.status != TaskStatus.TS_Running) {
                    if (task.status != TaskStatus.TS_Finished)
                        needForRefresh = true;
                    task.status = TaskStatus.TS_Finished;
                }
               
                if (stat != 0continue;
               
                String s = task.getOrders();
                for (TaskAccInfo inf : task.accountList) {
                    if (inf.status != TaskAccInfo.TS_Sending) continue;
                    // если задача не отправлена, отправляем
                    Terminal conn = form.server.get(inf.accID);
                    if (conn == null) continue;
                    if (tm - inf.lastTimeSending < 3000) continue; // чтобы не спамить по 10 раз в сек
                    inf.lastTimeSending = tm;
                    // упаковка задачи
                    PSPackage pkg = new PSPackage();
                    pkg.set("cmd", "execute-task");
                    pkg.set("id", task.id);
                    pkg.set("tm", Long.toString(task.timeStart/1000));
                    pkg.set("startNow", Boolean.toString(task.startNow));
                    pkg.set("orders", s);
                    conn.sendPackage(pkg);
                }
            }
        }
        // -- если требуется обновление таблицы задач
        if (needForRefresh) {
            try {
                EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        form.taskModel.refreshTaskList(TaskManager.this);
                    }
                });
            } catch (Exception e) {}
        }
    }
   
    /**
     * Добавление нового элемента в список задач
     * @param task новый элемент
     */
    public void addTask(Task task) {
        synchronized (taskList) {
            taskList.addFirst(task);
        }
    }
   
    /**
     * Проверка принадлежнасти ордера задаче по комментарию (OrderComment()).
     * @param comment комментарий ордера MT4
     * @return null, если ордер не идентифицирован, иначе - структура с задачей
     * и номером ордера в списке
     */
    public ReciveOrderCheck checkTaskOrder(String comment) {
        int i1 = comment.indexOf('{');
        int i2 = comment.indexOf('}', i1);
        if (i1 < 0 || i2 < 0) return null;
        StringTokenizer st = new StringTokenizer(comment.substring(i1 + 1, i2), ";");
        String id = st.nextToken();
        Iterator<Task> i = taskList.descendingIterator();
        while (i.hasNext()) {
            Task task = i.next();
            if (id.equals(task.id)) {
                try {
                    ReciveOrderCheck ans = new ReciveOrderCheck();
                    ans.task = task;
                    ans.index = Integer.parseInt(st.nextToken());
                    return ans;
                } catch (Exception e) {}
                return null;
            }
        }
        return null;
    }
   
    /**
     * Поиск задачи по идентификатору
     * @param id идентификатор
     * @return null, если задача не найдена
     */
    public Task taskByID(String id) {
        Iterator<Task> i = taskList.descendingIterator();
        while (i.hasNext()) {
            Task task = i.next();
            if (task.id.equals(id)) return task;
        }
        return null;
    }
   
    /**
     * Полный список задач. И уже выполненных, и исполняемых, и запланированных.
     * Сортировка идёт в обратном порядке - новые элементы добавляются не в
     * конец списка, а в начало.
     * <b>Внимание!</b> Обращения к списку должны быть засинхронизированы - объект
     * taskList не является thread-safe!
     */
    public final LinkedList<Task> taskList;
    /**
     * Класс главной формы приложения. Использование разрешено только через
     * поток диспетчеризации сообщений (синхронно с form)
     */
    private final MainForm form;
   
    public static Random rand = new Random();
   
    /**
     * Описание задачи. Содержит список ордеров и идентификационные данные.
     */
    public static class Task {
       
        public Task(String id) {
            this.id = id;
            orderList = new ArrayList<>();
            accountList = new ArrayList<>();
            startNow = false;
            status = TaskStatus.TS_Waiting;
            color = new Color(220 + rand.nextInt(35),
                    220 + rand.nextInt(35), 220 + rand.nextInt(35));
        }
       
        /**
         * Экспорт данной задачи в xml-node
         * @param node ветвь, выделенная исключительно только под данную задачу
         */
        public void exportToNode(Element node) {
            Document doc = node.getOwnerDocument();
            Element item = doc.createElement("parameters");
            item.setAttribute("name", name);
            item.setAttribute("id", id);
            item.setAttribute("status", status.name());
            item.setAttribute("time", Long.toString(timeStart));
            node.appendChild(item);
            // -- accounts data export
            item = doc.createElement("accounts");
            node.appendChild(item);
            for (TaskAccInfo accInfo : accountList) {
                Element accNode = doc.createElement("acc");
                accNode.setAttribute("id", Long.toString(accInfo.accID));
                accNode.setAttribute("status", Integer.toString(accInfo.status));
                item.appendChild(accNode);
            }
            // -- orders data export
            Element root = doc.createElement("orders");
            node.appendChild(root);
            for (TaskOrder o : orderList) {
                item = doc.createElement("o");
                item.setAttribute("smb", o.symbol);
                item.setAttribute("type", o.type.name());
                item.setAttribute("size", Double.toString(o.size));
                item.setAttribute("dev", Integer.toString(o.deviation));
                item.setAttribute("sl", Integer.toString(o.stoploss));
                item.setAttribute("tp", Integer.toString(o.takeprofit));
                item.setAttribute("trail", Integer.toString(o.trailing));
                item.setAttribute("time", Integer.toString(o.time));
                item.setAttribute("useBreakeven", Boolean.toString(o.useBreakeven));
                root.appendChild(item);
            }
           
        }
       
        /**
         * Импорт всех данных, касаемых данной задачи. Внимание - id задачи не
         * импортируется! id задаётся через конструктор!
         * @param node ветвь, содержащая в себе отдельную задачу
         */
        public void importFromNode(Element node) {
            orderList.clear();
            accountList.clear();
            Element item;
            // -- parameters
            NodeList nl = node.getElementsByTagName("parameters");
            if (nl.getLength() > 0) {
                item = (Element)nl.item(0);
                try {
                    name = item.getAttribute("name");
                    timeStart = Long.parseLong(item.getAttribute("time"));
                    String buffer = item.getAttribute("status");
                    if (!buffer.isEmpty()) status = TaskStatus.valueOf(buffer);
                } catch (Exception e) { e.printStackTrace(); }
            }
            // -- account data
            nl = node.getElementsByTagName("accounts");
            if (nl.getLength() > 0) {
                item = (Element)nl.item(0);
                nl = item.getElementsByTagName("acc");
                for (int i = 0; i < nl.getLength(); ++i) {
                    try {
                        Element a = (Element)nl.item(i);
                        TaskAccInfo acc = new TaskAccInfo(Long.parseLong(a.getAttribute("id")));
                        acc.status = Integer.parseInt(a.getAttribute("status"));
                        accountList.add(acc);
                    } catch (Exception e) { e.printStackTrace(); }
                }
            }
            // -- orders
            nl = node.getElementsByTagName("orders");
            if (nl.getLength() > 0) {
                item = (Element)nl.item(0);
                nl = item.getElementsByTagName("o");
                for (int i = 0; i < nl.getLength(); ++i) {
                    item = (Element)nl.item(i);
                    try {
                        TaskOrder o = new TaskOrder(item.getAttribute("smb"));
                        o.type = TaskOrder.Type.valueOf(item.getAttribute("type"));
                        o.size = Double.parseDouble(item.getAttribute("size"));
                        o.deviation = Integer.parseInt(item.getAttribute("dev"));
                        o.stoploss = Integer.parseInt(item.getAttribute("sl"));
                        o.takeprofit = Integer.parseInt(item.getAttribute("tp"));
                        o.trailing = Integer.parseInt(item.getAttribute("trail"));
                        o.time = Integer.parseInt(item.getAttribute("time"));
                        o.useBreakeven = Boolean.parseBoolean(item.getAttribute("useBreakeven"));
                        orderList.add(o);
                    } catch (Exception e) { e.printStackTrace(); }
                }
            }
        }
       
        /**
         * Получить список ордеров одной строкой. Нужно для отправки в MT4
         * @return
         */
        public String getOrders() {
            StringBuilder sb = new StringBuilder();
            for (TaskOrder order : orderList) {
                sb.append(order.deviation); sb.append(',');
                sb.append(order.size); sb.append(',');
                sb.append(order.symbol); sb.append(',');
                sb.append(order.stoploss); sb.append(',');
                sb.append(order.takeprofit); sb.append(',');
                sb.append(order.time); sb.append(',');
                sb.append(order.trailing); sb.append(',');
                sb.append(order.type.toString()); sb.append(',');
                sb.append(order.useBreakeven); sb.append(',');
                sb.append(";");
            }
            return sb.toString();
        }
       
        /**
         * Импорт задачи из xml-элемента node. Так же сразу создаёт экземпляр
         * класса Task.
         * @param node ветвь, выделенная именно под данную задачу
         * @return null, если в содержимом ветви есть ошибки
         */
        public static Task createFromNode(Element node) {
            Element item;
            String id = null;
            // -- parameters
            NodeList nl = node.getElementsByTagName("parameters");
            if (nl.getLength() > 0) {
                item = (Element)nl.item(0);
                try { id = item.getAttribute("id"); }
                catch (Exception e) { e.printStackTrace(); }
            }
            if (id == null) return null;
            Task task = new Task(id);
            task.importFromNode(node);
            return task;
        }
       
        @Override
        public String toString() {
            return name;
        }
       
        /**
         * Список ордеров в данной задаче
         */
        public final List<TaskOrder> orderList;
        /**
         * Список торговых счетов, на которых задача должна выполниться
         */
        public final List<TaskAccInfo> accountList;
       
        /**
         * Имя задачи (не имеет значения)
         */
        public String name;
        /**
         * Уникальный идентификатор задачи
         */
        public final String id;
        /**
         * Время отправки ордеров на рынок
         */
        public long timeStart;
        /**
         * Флаг: исполнять задачу сразу, если true
         */
        public boolean startNow;
        /**
         * Цвет фона для ордеров данной задачи (в таблице real-time торговли)
         */
        public final Color color;
       
        /**
         * Статус задачи
         */
        public TaskStatus status;
    }
   
    /**
     * Описание ордера в задаче. Такой ордер описывает только приказ на
     * открытие, и никак не описывает открытые или исторические ордера!
     */
    public static class TaskOrder {
       
        /**
         * Все поля заполняются стандартными данными
         * @param symbol валютная пара
         */
        public TaskOrder(String symbol) {
            this.symbol = symbol;
            type = Type.Both;
            size = 15;
            deviation = 90;
            stoploss = 110;
            takeprofit = 750;
            trailing = 85;
            time = 35;
            useBreakeven = true;
        }
       
        public String symbol;
        /**
         * Тип сделки
         */
        public Type type;
        /**
         * Размер сделки в процентах от текущего депозита.
         */
        public double size;
        /**
         * Отклонение от текущей рыночной цены. Указывается в пунктах
         */
        public int deviation;
        /**
         * Уровень стоплоса. Указывается в пунктах
         */
        public int stoploss;
        /**
         * Уровень тейкпрофита. Указывается в пунктах.
         */
        public int takeprofit; // pips
        /**
         * Трейлинг-стоп. Указывается в пунктах.
         */
        public int trailing; // pips
        /**
         * Время существования сделки. Указывается в секундах.
         */
        public int time; // seconds
        /**
         * Использовать уровень безубытка. Это значит, что будет установлен
         * минимально возможный Stoploss, по преодолению которого ордер
         * закроется с profit'ом равным нулю.
         */
        public boolean useBreakeven;
       
        @Override
        public String toString() {
            return symbol;
        }
       
        public static enum Type { Buy, Sell, Both }
    }
   
    /**
     * Класс предназначен для информирования о том, на каких счетах следует
     * запускать задачу, и на каких счетах она уже запущена
     */
    public static class TaskAccInfo {
       
        /**
         * Статус задачи: отправка в торговый терминал
         */
        public final static int TS_Sending = 0;
        /**
         * Статус задачи: запущена в торговом терминале
         */
        public final static int TS_Started = 1;
        /**
         * Статус задачи: завершена в торговом терминале
         */
        public final static int TS_Finished = 2;
       
        public TaskAccInfo(long accountID) {
            this.accID = accountID;
            status = TS_Sending;
            lastTimeSending = 0;
        }
       
        /**
         * Идентификатор торгового счёта
         */
        public final long accID;
        /**
         * Статус исполнения задачи
         */
        public int status;
        /**
         * Время последней попытки отправки
         */
        public long lastTimeSending;
    }
   
    /**
     * Результат функции checkTaskOrder().
     */
    public static class ReciveOrderCheck {
        Task task = null;
        int index = -1;
    }
   
    /**
     * Статуст задачи в целом
     */
    public enum TaskStatus {
       
        /**
         * Ожидание - состояние, в котором система ждёт указанног овремени
         * отправки ордеров. Вернее, ожидание закончится за минуту до указанного
         * времени, и начнётся отправка ордеров.
         */
        TS_Waiting      ("Ожидание"),
        /**
         * Отправка ордеров длится 30 секунд для моментальных задач, и 55 для
         * отложенных. При этом, для отложенных отправка выполняется не после
         * указанного времени, и за минуту до указанного времени.
         */
        TS_Sending      ("Отправка"),
        /**
         * Означает, что mql-робот принял пакет ордеров и начал его обработку.
         */
        TS_Running      ("Выполняется"),
        /**
         * Означает, что задача завершена. Либо об этом оповестил mql, либо
         * эта задача вовсе не попала в торговый терминал - она в любом случае
         * будет завершённой.
         */
        TS_Finished     ("Завершена");

        private TaskStatus(String description) {
            this.description = description;
        }
       
        /**
         * Описание статуса (для вывода на экран)
         */
        public final String description;
    }
}
TOP

Related Classes of psconsole.TaskManager$ReciveOrderCheck

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.