...

суббота, 5 октября 2019 г.

[Из песочницы] Сертифицированный мониторинг температуры

В нашей компании используется Система менеджмента качества (СМК). В рамках одной из сертификации по системе ISO:9001 было предписано собирать показания температуры и влажность в некоторых помещениях, например в серверной или на складах.

Т.к. все бюрократические процедуры требуют бумажек, то и сбор данных должен производиться устройством имеющим поверку.

В связи с этим был повешен самый обычный гигрометр и на протяжении нескольких лет люди ежедневно записывали показания в журнал. Согласитесь, неудобно.


Дабы автоматизировать данную процедуру были начаты поиски устройства для сбора температуры и влажности.

Цель была как то собирать данные и передавать все это в Zabbix. (для СМК не обязателен заббикс, любое место хранения, но делать еще какую то отдельную систему под мониторинг температуры не хотелось).

В принципе было много готовых комплектов для этого, например Equicom PING3 или netping и таких примеров еще куча, так же можно было собрать свою систему на arduino или raspeberry,
но все эти варианты не подходили т.к. все они не имеют сертификации, а точнее метрологической поверки, а следовательно и не могут считаться официальными средствами измерения и не подходят для прохождения ISO:9001.

В итоге был найден прибор умеющий отдавать данные по ethernet и входящий в реестр измерительных средств. Им оказался «Ивит-М.Е.» разработанный в Новосибирске, там же и производящийся. Заказали (заказ кстати идет долго. срок изготовления около месяца, плюс поверка, плюс доставка до Москвы).

Приходит все это вот в таком виде. Когда берешь в руки сразу понимаешь что это российское производство :-)

Блок питания(заказывается отдельно) не подключен к датчику.

По этому разбираем его и начинаем подключать.

Вход подключаем все равно как. ток переменный. я использовал обычный силовой кабель от компа.

На выходе постоянный ток. плюс и минус подписаны прям на плате.

Дальше подключаем провода непосредственно к самому датчику. Согласно инструкции

Сами клеммы выглядят вот так:

Откручиваем, снимаем и из Г-образной половинки выковыриваем вкладыш.
Подключаем питание и сеть.

В итоге получается нечто такое:

Из минусов данного устройства — он не умеет отдавать данные по SNMP, работает по протоколу Modbus.

В принципе есть много SCADA систем и OPC серверов умеющих читать по Modbus, но большинство из них либо платные, либо собирают в какую то свою базу данных из которой тоже не понятно как вытаскивать данные для передачи их в дальнейшем заббиксу.

По этому был написан небольшой скрипт на питоне для прямого обращения к датчику.
Данные в регистрах хранятся в виде float и приходят при обращении к ним вот в таком виде

READ_INPUT_REGISTERS (16855, 57976)

Для конфигурирования датчика есть приложение config-ivit.exe

Настроек там не очень много. можно настроить сеть, почту.

в конфигураторе регистры указаны в 16речной системе, но в питоновском скрипте нужно указывать регистры в 10-тичной системе.

Приводим данные к нормальному читаемому виду согласно стандарту ieee-754.

Реализовать передачу данных полученных от скрипта в заббикс можно двумя путями.

Первый способ: с помощью userparametr, на какой-нибудь узел, где установлен питон и заббикс агент. У меня, например, был на самом заббикс сервере.

import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
import sys

def check_reg(reg,ip):
    reg = int(reg)
    master = modbus_tcp.TcpMaster(host=ip, port=int(502))
    master.set_timeout(1.0)
    getDI = master.execute(1,cst.READ_INPUT_REGISTERS, reg, 2)
    Num1 = str(bin(getDI[0]))[2:]
    while len(Num1) < 16:
        Num1 = '0' + Num1

    Num2 = str(bin(getDI[1]))[2:]
    while len(Num2) < 16:
        Num2 = '0' + Num2

    res = Num1 + Num2
    znak = int(res[0], 2)
    znak2 = (0 - 1) ** znak
    e = int(res[1:9], 2) - 127
    exp = 2 ** e
    m = 1 + (int(res[9:], 2) / float(2 ** 23))
    F = znak2 * exp * m
    print(round(F, 1))

check_reg(sys.argv[1],sys.argv[2])

Со стороны заббикса в zabbix_agentd.conf указываем:
UserParameter=check_reg[*], /usr/bin/python /home/appliance/scada.py $1 $2

В самом заббиксе нам нужно будет передать только номер регистра и IP адрес устройства к кому мы хотим обратиться:

например: check_reg[22,192.168.100.100]

Номера регистров:

22 — Влажность
34 — Температура
36 — Точка росы

Второй способ: передавать значения через zabbix_sender. Этот способ удобен тем, что можно создать отдельный узел сети у которого не будет агента, и соответственно можно будет сделать шаблон для многих устройств.

import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp
import sys, os

def check_reg(reg,ip):
    reg = int(reg)
    master = modbus_tcp.TcpMaster(host=ip, port=int(502))
    master.set_timeout(1.0)
    getDI = master.execute(1,cst.READ_INPUT_REGISTERS, reg, 2)
    Num1 = str(bin(getDI[0]))[2:]
    while len(Num1) < 16:
        Num1 = '0' + Num1

    Num2 = str(bin(getDI[1]))[2:]
    while len(Num2) < 16:
        Num2 = '0' + Num2

    res = Num1 + Num2
    znak = int(res[0], 2)
    znak2 = (0 - 1) ** znak
    e = int(res[1:9], 2) - 127
    exp = 2 ** e
    m = 1 + (int(res[9:], 2) / float(2 ** 23))
    F = znak2 * exp * m
    return round(F, 1)

os.system('zabbix_sender -z 127.0.0.1 -s Ivit1  -k Humidity -o '+ str(check_reg(22,sys.argv[1])))
os.system('zabbix_sender -z 127.0.0.1 -s Ivit1  -k Temper -o '+ str(check_reg(34,sys.argv[1])))
os.system('zabbix_sender -z 127.0.0.1 -s Ivit1  -k Rosa -o '+ str(check_reg(36,sys.argv[1])))


Дальше остается только запустить этот скрипт на выполнение по крону указав только лишь ip адрес устройства
*/1 * * * * /home/ivitsender.py 192.168.100.100

Дальше настраиваем тригеры которые для нас считаются критичными. минимальная/максимальная температура, влажность.

Вот и все. Таким образом мы получили сертифицированный мониторинг температуры, который подходит для прохождения СМК и ISO:9001

Let's block ads! (Why?)

Звуки для UI: подборка тематических ресурсов

Рассказываем о площадках, где можно найти и скачать аудиосемплы для озвучки пользовательского интерфейса. Подборка пригодится тем, кто разрабатывает приложения или игры.


Это — набор интерактивных звуков для графических интерфейсов мобильных приложений. В нем есть звуки кнопок, ошибок, а также оповещений и уведомлений. Прослушать их можно онлайн на странице проекта. Авторами библиотеки выступили дизайнеры из Facebook. Они говорят, что семплы из подборки задействовали в разработке скетч-приложений Origami и Framer.

Лицензия: Неисключительная — разрешает использовать звуки при разработке прототипов приложений и мокапов. Аудиофайлы из библиотеки также можно задействовать в коммерческих программных продуктах — но в этом случае обязательно указание авторства, лицензии и ссылки на неё. Однако если ваше приложение — это инструмент для дизайнеров, подобный Origami или Framer, нужно предварительно взять разрешение у команды Facebook Design.

Особенности: Sound Kit содержит две папки — Full Volume и Low Volume. В первой лежат аудиофайлы с громкостью -5 дБ. Они подходят для показа прототипов на компьютере. Громкость звуков, лежащих во второй папке, снижена и составляет -20 дБ. Авторы говорят, что они подойдут для демонстрации приложения на мобильном — в этом случае динамик не будет искажать звук. В библиотеку входят 39 аудиофайлов, но авторы не обновляли этот набор с 2017 года.



150 аудиосемплов для озвучивания интерфейсов в играх и других проектах.

Лицензия: Royalty-free — семплы можно модифицировать и использовать в коммерческих целях.

Особенности: На сайте есть и другие подборки — с Sci-Fi и EDM-семплами. Имеется поиск по форматам файлов (WAV, MP3, OGG, AIFF и FLAC), а также частоте дискретизации (например, 44,1 или 96 кГц). Чтобы скачать аудиосемплы, потребуется регистрация.




Фото Hal Gatewood / Unsplash

Бесплатный сэт UI-звуков для iOS. Её автор — Фред Шоуэлл (Fred Showell), продуктовый дизайнер из австралийской компании LiveTiles, разрабатывающей программное обеспечение. Фред говорит, что собрал Octave из собственной библиотеки семплов, которую собирал последние десять лет.

Лицензия: Звуки разрешено использовать в любых проектах — как личных, так и коммерческих. Указание авторства не требуется, но желательно. Конечно, саму библиотеку продавать нельзя.

Особенности: В подборку вошли 48 звуков — гудков, шлепков и др. — в формате AIFF с частотой дискретизации 44.1 кГц. К ним сразу прилагается файл с UIButton Category, который упрощает назначение звуков событиям в iOS и OS X. В коде приложения достаточно прописать:

[myButton setSoundNamed:@"mySound.aif" forControlEvent: UIControlEventTouchUpInside]

На сайте есть технические рекомендации по работе со звуком в приложениях на iPad и iPhone и проектированию UI. Также автор принимает заказы на разработку кастомных звуков.

Библиотека из 500 звуков для графических интерфейсов в приложениях и играх. Её составил аудиодизайнер из Германии — Мартин Страка (Martin Straka). Он пишет семплы для приложений и саундтреки к играм на протяжении десяти лет. Например, он выступил композитором для проектов Spirits и Mr. Bounce.


Его треки даже номинировали на приз Independent Games Festival — это конференция для независимых разработчиков компьютерных игр.

Лицензия: Все семплы royalty-free, их можно использовать для любых целей — как коммерческих, так и некоммерческих. Указание авторства при этом не требуется.

Особенности: К сожалению, бесплатно распространяются только 11 аудиофайлов. Чтобы их получить, достаточно запросить демо на сайте. За остальной набор придется отдать 29 долларов. Также автор может записать уникальные звуки по заказу.



Это не простая библиотека семплов. Это — медиа-архив со звуками, музыкой, а также 2D, 3D-артом и текстурами. Его разработал инженер Барт Келси (Bart Kelsey) еще в 2009 году. С тех пор портал обзавёлся обширным сообществом — новый контент туда заливают примерно каждые 20 минут.

Лицензия: Контент, представленный на OpenGameArt, защищён свободными лицензиями. Среди них: GNU General Public License, LGPL, а также Creative Commons, включая Attribution, Attribution Share Alike и CC0. Все файлы разрешено использовать в коммерческих целях.

Особенности: Количество подборок со звуками (в том числе для UI) превышает тысячу. Чтобы в этом многообразии было проще ориентироваться, на сайте работает поиск — по названию, тегам или лицензиям.



Что еще почитать в нашем «Мире Hi-Fi»:

Прислушиваясь к информационному шуму: музыка и видео, которые никто не должен был найти
«Находки аудиомана»: карты звуков как способ погрузиться в атмосферу незнакомого города
Что такое музыкальное программирование — кто и почему им занимается

Как ПК завоевал медиаиндустрию с помощью ПО: обсуждаем Pro Tools и Media Composer
Где взять аудиосемплы для ваших проектов: подборка из девяти тематических ресурсов
В чем особенности и задачи звукового сопровождения игр


Let's block ads! (Why?)

[Из песочницы] Рукоблудие вокруг ImmutableList в Java

Прочитал статью "Неизменяемых коллекций в Java не будет – ни сейчас, ни когда-либо" и подумал, что проблема отсутствия в Java неизменяемых списков, из-за которой грустит автор статьи, вполне решаема в ограниченных масштабах. Предлагаю свои мысли и куски кода на этот счёт.

(Это статья-ответ, прочитайте сначала исходную статью.)


UnmodifiableList vs ImmutableList

Первый возникший вопрос: для чего нужен UnmodifiableList, если есть ImmutableList? По итогам обсуждения в комментариях исходной статьи видятся две идеи касательно смысла UnmodifiableList:


  • метод получает UnmodifiableList, сам его менять не может, но знает, что содержимое может быть изменено другой нитью (и умеет это корректно обрабатывать)
  • другие нити не влияют, UnmodifiableList и ImmutableList получаются равнозначны для метода, но UnmodifiableList используется как более «легковесный».

Первый вариант представляется слишком редким на практике. Таким образом, если удастся сделать «лёгкую» реализацию ImmutableList, то UnmodifiableList становится не особо нужным. Поэтому в дальнейшем забудем про него и будем реализовывать только ImmutableList.


Постановка задачи

Будем реализовывать вариант ImmutableList:


  • API должно быть идентично API обычного List в «читающей» части. «Пишущая» часть должна отсутствовать.
  • ImmutableList и List не должны быть связаны отношениями наследования. Почему так – разбирается в исходной статье.
  • Реализацию имеет смысл делать по аналогии с ArrayList. Это самый простой вариант.
  • Реализация должна по возможности избегать операций копирования массивов.

Реализация ImmutableList

Сначала разбираемся с API. Исследуем интерфейсы Collection и List и копируем из них «читающую» часть в свои новые интерфейсы.

public interface ReadOnlyCollection<E> extends Iterable<E> {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean containsAll(Collection<?> c);
}

public interface ReadOnlyList<E> extends ReadOnlyCollection<E> {
    E get(int index);
    int indexOf(Object o);
    int lastIndexOf(Object o);
    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index);
    ReadOnlyList<E> subList(int fromIndex, int toIndex);
}

Далее создаём класс ImmutableList. Сигнатура аналогична ArrayList (но реализует интерфейс ReadOnlyList вместо List).

public class ImmutableList<E> implements ReadOnlyList<E>, RandomAccess, Cloneable, Serializable

Реализацию класса копируем из ArrayList и жёстко рефакторим, выкидывая оттуда всё связанное с «пишущей» частью, проверки на concurrent modification и т.д.

Конструкторы будут такие:

public ImmutableList()
public ImmutableList(E[] original)
public ImmutableList(Collection<? extends E> original)

Первый создаёт пустой список. Второй создаёт список, копируя массив. Без копирования тут не обойтись, если уж мы хотим добиться immutable. С третьим интереснее. Аналогичный конструктор ArrayList также копирует данные из коллекции. Мы будем поступать так же, за исключением случаев, когда orginal является экземпляром ArrayList или Arrays$ArrayList (это то, что возвращается методом Arrays.asList()). Можно смело считать, что эти случаи покроют 90% вызовов конструктора.

В этих случаях мы будем «красть» у original массив через reflections (есть надежда, что это быстрее, чем копировать гигабайтные массивы). Суть «кражи»:


  • добираемся до private поля original, хранящего массив (ArrayList.elementData)
  • копируем ссылку на массив к себе
  • помещаем в исходное поле null
protected static final Field data_ArrayList;
static {
    try {
        data_ArrayList = ArrayList.class.getDeclaredField("elementData");
        data_ArrayList.setAccessible(true);
    } catch (NoSuchFieldException | SecurityException e) {
        throw new IllegalStateException(e);
    }
}

public ImmutableList(Collection<? extends E> original) {
    Object[] arr = null;
    if (original instanceof ArrayList) {
        try {
            arr = (Object[]) data_ArrayList.get(original);
            data_ArrayList.set(original, null);
        } catch (@SuppressWarnings("unused") IllegalArgumentException | IllegalAccessException e) {
            arr = null;
        }
    }

    if (arr == null) {
        //либо получили не ArrayList, либо украсть массив не получилось - копируем
        arr = original.toArray();
    }

    this.data = arr;
}

В качестве контракта примем, что при вызове конструктора происходит конвертация изменяемого списка в ImmutableList. Исходный список после этого использовать нельзя. При попытке использования прилетает NullPointerException. Это гарантирует, что «украденный» массив не будет меняться и наш список будет действительно immutable (за исключением варианта, когда некто доберётся до массива через reflections).


Прочие классы

Предположим, что мы решили использовать ImmutableList в реальном проекте.

Проект взаимодействует с библиотеками: получает от них и отправляет им различные списки. В подавляющем большинстве случаев этими списками окажутся ArrayList. Описанная реализация ImmutableList позволяет быстро конвертировать получаемые ArrayList в ImmutableList. Требуется также реализовать конвертацию для отправляемых в библиотеки списков: ImmutableList в List. Для быстрой конвертации нужна обёртка ImmutableList, реализующая List, выкидывающая исключения при попытке записи в список (по аналогии с Collections.unmodifiableList).

Также проект сам как-то обрабатывает списки. Имеет смысл создать класс MutableList, представляющий изменяемый список, с реализацией на основе ArrayList. В этом случае можно отрефакторить проект, подставив вместо всех ArrayList класс, явно декларирующий намерения: либо ImmutableList, либо MutableList.

Нужна быстрая конвертация из ImmutableList в MutableList и обратно. При этом, в отличие от преобразования ArrayList в ImmutableList, исходный список портить мы уже не можем.

Конвертация «туда» обычно будет получаться медленной, с копированием массива. Но для случаев, когда полученный MutableList изменяется не всегда, можно сделать обёртку: MutableList, который сохраняет ссылку на ImmutableList и использует его для «читающих» методов, а если вызван «пишуший» метод, то только тогда забывает про ImmutableList, предварительно скопировав содержимое его массива к себе, и далее работает уже со своим массивом (что-то отдалённо похожее есть в CopyOnWriteArrayList).

Конвертация «обратно» подразумевает получение snapshot-а содержимого MutableList на момент вызова метода. Опять же, в большинстве случаев без копирования массива не обойтись, но можно сделать обёртку для оптимизации случаев нескольких конвертаций, между которыми содержимое MutableList не менялось. Ещё один вариант конвертации «обратно»: некие данные собираются в MutableList, и когда сбор данных завершён, MutableList требуется преобразовать навсегда в ImmutableList. Реализуется также без проблем ещё одной обёрткой.


Итого

Результаты эксперимента в виде кода выложены тут

Реализован сам ImmutableList, описанное в разделе «Прочие классы» (пока?) не реализовано.

Можно считать, что посыл исходной статьи «неизменяемых коллекций в Java не будет» ошибочен.

Если есть желание, то вполне можно использовать подобный подход. Да, с небольшими костылями. Да, не в рамках всей системы, а только в своих проектах (хотя если многие проникнутся, то и в библиотеки оно постепенно подтянется).

Одно но: если есть желание… (Таити, Таити… Не были мы ни в какой Таити! Нас и здесь неплохо кормят.)

Let's block ads! (Why?)

Линус Торвальдс одобрил внедрение функции ограничения прав суперпользователя Lockdown в версии ядра 5.4 ОС Linux

На днях стало известно о том, что Линус Торвальдс одобрил добавление новой функции безопасности в ядро Linux. Она называется Lockdown и предназначена для ограничения прав суперпользователя. Появится функция в версии ядра 5.4, причем речь идет именно о «ванильном» ядре, а не дистрибутивах.

Функцию добавят под видом модуля безопасности LSM (Linux Security Module). В результате процессы, которые запущены в пространстве пользователя, будут разграничены более жестко, с кодом ядра запретят взаимодействовать даже привилегированным аккаунтам.
Правда, функция опциональная, ее не будут включать по дефолту. Разработчики считают, что если это сделать, то может быть нарушена работа уже существующих и настроенных систем. Тем не менее, подобный подход, по мнению экспертов, должен значительно повысить уровень устойчивости ОС на базе Linux к атакам злоумышленников.

В настоящее время киберпреступник, который получает права суперпользователя, получает возможность выполнить произвольный код на уровне ядра. А для этого ему требуется просто записать этот код в память ядра через виртуальное устройств /dev/kmem либо же выполнить подмену уже запущенного ядра свой копией, воспользовавшись механизмом kexec. Таким образом, взломщик получит доступ к конфиденциальным данным, которые хранятся на уровне ядра, либо же обойдет механизм безопасной загрузки UEFI Secureboot, одновременно скрыв факт своего присутствия в системе.

А вот активация модуля Lockdawn позволяет заблокировать доступ пользовательских процессов к памяти ядра через /dev/kmem, /dev/kmem и /dev/port. Кроме того, выполняется запрет на выполнение системных вызовов, которые используются для загрузки нового ядра (kexec_load, k_exec_file_load). Есть и ограничение на возможности по изменению режима портов ввода/вывода, плюс ряд других возможностей.

Модуль, по данным разработчиков, получает сразу два режима блокировки. Первый — integrity, второй — confidentiality. В первом случае запрещается внесение изменений в работу уже запущенного ядра. Второй же не дает возможности считывать конфиденциальную информацию. В случае необходимости разработчики могут добавлять собственные режимы работы системы защиты ядра. Правда, здесь нужно использовать отдельные патчи.

Что касается идеи внедрения Lockdown, то у этого процесса долгая история, которая началась еще в 2010 году. Изначально проект возглавлял Мэтью Гаррет, который предложить разработать и внедрить такой механизм обеспечения безопасности, который не даст другим пользователям вмешиваться в работу ядра ОС.

С течением времени к пониманию необходимости реализации такой функции стали приходить и другие эксперты. Тем не менее, разработчикам не удавалось согласовать свои предложения. Ситуация усугублялась еще и тем, что против включения кода Lockdown выступал Линус Торвальдс. Тем не менее, многие дистрибутивы самостоятельно внедрили этот модуль.

Но в 2018 году Торвальдс принял решение согласиться с мнением сообщества, после чего внедрение Lockdown в ванильное ядро стало лишь вопросом времени.

Кстати, Линус Торвальдс долгое время не соглашался с точкой зрения некоторых специалистов по кибербезопасности, которые предлагали тем либо иным образом влиять на работу ядра. В 2017 году один из разработчиков предложил внести в версию ядра v4.15-rc1 созданный им механизм hardened usercopy.

Торвальдс тогда отреагировал крайне жестко, заявив, что специалисты по безопасности должны заниматься своим делом, то есть устранять уязвимости. А вот поиском возможностей изменить работу ядра они заниматься не должны, это прерогатива других экспертов. Линус Торвальдс тогда назвал предложения Кука убийством ядра.

Let's block ads! (Why?)

[Из песочницы] Оптимизация портфеля облигаций с применением библиотеки ALGLIB

В статье пойдет речь об опыте разработки программы для составления эффективного портфеля облигаций с точки зрения минимизации его дюрации. Возможно, я не буду оригинален и для всех, кто инвестирует в облигации вопросы определения оптимальных весов давно решены, но все же, надеюсь, описанный подход и приведенный программный код будут кому-то полезны.

Статья, ввиду наличия в ней не малого объема математики, кому-то может показаться усложненной. Но если уж Вы решили заняться инвестициями, то нужно быть готовым к тому, что в финансовой реальности часто встречается математика и еще значительно сложнее.

Исходные коды программы и пример портфеля для оптимизации выложены на GitHub.

Итак, имеем задачу сформировать эффективный портфель облигаций.


С точки зрения минимизации несистемных рисков (ради чего и диверсифицируется портфель) выбор бумаг осуществлялся рассмотрением параметров конкретного выпуска, эмитента (если не ограничиваться ОФЗ), поведением бумаги и т.д. (подходы к такому анализу достаточно индивидуальны для каждого инвестора и в данной статье не рассматриваются).

Отобрав, несколько бумаг, наиболее предпочтительных для инвестирования, возникает естественный вопрос: сколько штук облигаций каждого выпуска нужно купить? Это и есть задача оптимизации портфеля так, чтобы риски портфеля были минимальны.

В качестве оптимизируемого параметра естественно рассмотреть дюрацию. Таким образом, задача сводится к тому, чтобы определить веса бумаг в портфеле, такие, при которых дюрация портфеля была бы минимальной при некоторой фиксированной доходности портфеля. Здесь необходимо сделать несколько оговорок:

  1. Дюрация портфеля облигаций определяется входящими в его состав бумагами. Эти дюрации известны (они в открытом доступе). Дюрация портфеля не равна максимальной дюрации, входящих в него бумаг (есть такое заблуждение). Зависимость между дюрациями отдельных бумаг и дюрацией всего портфеля не линейна, т.е. не равна средневзвешенной дюрации составляющих его облигаций (Для того, чтобы убедиться в этом достаточно рассмотреть формулу дюрации (см. ниже (1)) и попытаться вычислить средневзвешенную дюрацию условного портфеля, состоящего, например, из двух бумаг. Подставив в такое выражение формулу для дюрации каждой бумаги, на выходе получим не формулу для дюрации портфеля, а некий «бред», с двумя ставками дисконтирования и несогласованными денежными потоками в качестве весов).
  2. В отличие от дюрации, доходность портфеля, зависит от доходностей, входящих в него инструментов линейно. Т.е. разместив деньги в несколько инструментов с фиксированной доходностью, мы получим доходность, прямо пропорциональную объемам вложений в каждый инструмент (причем это работает и для сложной ставки, а не только для простой). Убедиться в этом еще проще.
  3. В качестве ставки доходности облигаций используется доходность к погашению (YTM). Она обычно и применяется для расчета дюрации. Однако, доходность к погашению всего портфеля здесь довольно условна, т.к. срок до погашения у всех бумаг разный. При формировании портфеля эту особенность необходимо учитывать в том смысле, что портфель должен пересматриваться, не реже чем инструменты, из которых он составлен, выходят из оборота.

Итак, первой задачей является корректное вычисление дюрации самого портфеля. Непосредственным способом сделать это является: определение всех платежей по портфелю, вычисление доходности к погашению, дисконтирование платежей, умножение полученных величин на сроки этих платежей и суммирование. Для того, чтобы это проделать нужно объединить календари платежей всех инструментов в единый календарь платежей по всему портфелю, составить выражение для расчета доходности к погашению, вычислить её, дисконтировать по ней каждый платеж, умножить на его срок выплаты, сложить…. В общем, кошмар. Даже для двух бумаг проделать такое – очень трудоемкая задача, не говоря уж о том, чтобы в дальнейшем портфель регулярно пересчитывать. Такой путь нам не подходит.

Следовательно, необходимо искать возможность определить дюрацию портфеля иным, более быстрым способом. Приемлемым вариантом будет такой, который позволяет определить дюрацию портфеля по известным дюрациям инструментов. Исследования формулы дюрации показали, что такой путь имеется и здесь я бы хотел привести его подробно (если кому-то математические детали вычислений не интересны, можно смело пропустить несколько абзацев с формулами и перейти сразу к рассмотрению примера).

Дюрация долгового инструмента определяется следующим образом:

$$display$$ \begin{equation} D = \frac{\sum_{i}PV_i\cdot t_i}{\sum_{i}PV_i} ~~~~~~~~~~~~~(1) \end{equation} $$display$$

где:
  • ti — момент времени i-го платежа;
  • $inline$\begin{equation} PV_i = \frac{CF_i}{(1+r)^{t_i}} \end{equation}$inline$ — i-ый дисконтированный платеж;
  • CFi — i-ый платеж;
  • r — ставка дисконтирования.

Введем коэффициент дисконтирования k=(1+r) и будем рассматривать сумму дисконтированных платежей P как функцию от k:

$$display$$\begin{equation} P(k) = \sum_{i}PV_i = \sum_{i}{\frac{CF_i}{k^{t_i}}} ~~~~~~~~~~~~~(2) \end{equation}$$display$$

Дифференцируя P по k получаем

$$display$$\begin{equation} P'(k) = -\sum_{i}{t_i\frac{CF_i}{k^{t_i+1}}} = -\frac{1}{k}\sum_{i}{t_i\frac{CF_i}{k^{t_i}}} ~~~~~~~~~~~~~(3) \end{equation}$$display$$

С учетом последнего, выражение для дюрации облигации приобретает вид

$$display$$ \begin{equation} D = -k\frac{P'(k)}{P(k)} ~~~~~~~~~~~~~(4) \end{equation} $$display$$

При этом напомним, что в качестве ставки дисконтирования r в случае с облигацией применяется доходность к погашению (YTM).

Полученное выражение справедливо для одной облигации, но нас интересует портфель облигаций. Перейдем к определению дюрации портфеля.

Введем следующие обозначения:

  • Pi — цена i-ой облигации;
  • zi — количество бумаг i-ой облигации в портфеле;
  • ki — коэффициент дисконтирования i-ой облигации в портфеле;
  • $inline$\begin{equation} P_p = \sum_{i}{z_iP_i} \end{equation}$inline$ — цена портфеля;
  • $inline$\begin{equation} w_i = \frac{z_iP_i}{\sum_{i}z_iP_i} = \frac{z_iP_i}{P_p} \end{equation}$inline$ — вес i-ой облигации в портфеле; очевидно требование $inline$\begin{equation} \sum_{i}w_i = 1 \end{equation}$inline$;
  • $inline$\begin{equation} k_p = \sum_{i}w_ik_i \end{equation}$inline$ — коэффициент дисконтирования портфеля;

В силу линейности дифференцирования справедливо следующее:

$$display$$ \begin{equation} P'_p(k) = \left(\sum_{i}z_iP_i(k)\right)' = \sum_{i}z_iP'_i(k) ~~~~~~~~~~~~~(5) \end{equation} $$display$$

Таким образом, с учетом (4) и (5), дюрация портфеля может быть выражена как

$$display$$ \begin{equation} D_p = -k_p\frac{P'_p}{P_p} = -\sum_{i}w_ik_i\left(\frac{\sum_{j}z_jP'_j}{\sum_{j}z_jP_j}\right) ~~~~~~~~~~~~~(6) \end{equation} $$display$$

Из (4) однозначно следует $inline$\begin{equation} P'_j = -\frac{D_jP_j}{k_j} \end{equation}$inline$.
Подставляя данное выражение в (6) приходим к следующей формуле для дюрации портфеля:

$$display$$ \begin{equation} D_p = \sum_{i}w_ik_i\left(\frac{\sum_{j}\frac{D_j}{k_j}z_jP_j}{\sum_{j}z_jP_j}\right) = \left(\sum_{i}w_ik_i\right)\left(\sum_{j}w_j\frac{D_j}{k_j}\right) ~~~~~~~~~~~~~(7) \end{equation} $$display$$

В условиях, когда дюрация и доходность к погашению каждого инструмента известны (а мы, напомню, находимся именно в таких условиях) выражение (7) и есть искомая формула для определения дюрации портфеля на основе дюрации входящих в него облигаций. Она только с виду кажется сложной, но на самом деле она уже готова к применению на практике с помощью простейших функций MS Excel, что мы сейчас и проделаем на примере.

Пример


Для расчета дюрации портфеля по формуле (7) нам необходимы исходные данные, включающие собственно набор бумаг, входящих в портфель, их дюраций и доходностей к погашению. Как было сказано выше, данная информация имеется в открытом доступе, например, на сайте rusbonds.ru в разделе анализ облигаций. Исходные данные можно скачать в формате Excel.

В качестве примера рассмотрим портфель бумаг, состоящий из 9 облигаций. Исходная таблица с данными, скачанная с rusbonds, имеет следующий вид.

Красным выделены две интересующие нас колонки с дюрацией (колонка Е) и доходностью к погашению (колонка L = YTM).

Зададим веса w облигациям в данном портфеле (пока произвольным образом, но так, чтобы их сумма равнялась единице) и рассчитаем k = (1 + YTM/100) и D/k = («колонка Е»/k). Преобразованная таблица (без лишних колонок) будет иметь вид

Далее рассчитаем произведения $inline$\begin{equation}w_j\frac{D_j}{k_j}\end{equation}$inline$ и $inline$\begin{equation}w_ik_i\end{equation}$inline$ и просуммируем их, а полученные суммы умножим одну на другую. Результат этого умножения и составит искомую дюрацию при заданном распределении весов.

Итак, искомая дюрация портфеля равна 466,44 дня. Важно отметить, что в данном конкретном случае рассчитанная по формуле (7) дюрация очень незначительно отличается от средневзвешенной дюрации, рассчитанной с теми же весами (отклонение <0,5 дня). Однако эта разница увеличивается при увеличении разброса весов. Также она будет возрастать и при увеличении разброса дюраций бумаг.

После того, как нами получена формула для расчёта дюрации портфеля, следующим шагом является определение таких весов бумаг, чтобы при некоторой заданной доходности расчетная дюрация портфеля была бы минимальна. Переходим к следующей части – оптимизации портфеля.


Выражение (7) является квадратичной формой, с матрицей

$$display$$\begin{equation} A = \left\{ k_i\frac{D_j}{k_j}\right\} = \begin{pmatrix} D_1 & \ldots & k_1\frac{D_n}{k_n}\\ \vdots & D_j & \vdots\\ k_n\frac{D_1}{k_1} & \ldots & D_n \end{pmatrix} \end{equation}$$display$$

Соответственно, в матричной форме выражение для дюрации портфеля (7) можно записать так:

$$display$$\begin{equation} D_p = w^TAw ~~~~~~~~~~~~~(8) \end{equation}$$display$$

где w – вектор-столбец весов облигаций в портфеле. Как было сказано выше, сумма элементов вектора w должна быть равна единице. С другой стороны, выражение $inline$k_p = \sum_{i} w_i k_i$inline$ (которое, по сути, является простым скалярным произведением (w,k), где k – вектор коэффициентов дисконтирования облигаций) должно равняться целевой ставке дисконтирования портфеля, а значит задана и целевая доходность портфеля.

Таким образом, задача оптимизации портфеля облигаций сводится к минимизации квадратичной функции (8) с линейными ограничениями.

Классическим способом нахождения условного экстремума функции нескольких переменных является метод множителей Лагранжа. Однако здесь данный метод не применим хотя бы потому, что матрица A вырождена по построению (но не только в силу этого; подробности анализа применимости метода Лагранжа здесь опускаем, чтобы не перегружать статью избыточным математическим контентом).

Невозможность применить легкий и доступный аналитический метод приводит к необходимости использования численных методов. Задача оптимизации квадратичной функции хорошо известна и имеет несколько давно разработанных эффективных алгоритмов, реализованных в общедоступных библиотеках.

Для решения конкретно этой задачи применялась библиотека ALGLIB и реализованные в ней алгоритмы квадратичной оптимизации — QP-Solvers, входящие в пакет minqp.

Задача квадратичной оптимизации в общем виде выглядит следующим образом:

Требуется найти n-мерный вектор w, минимизирующий функцию

$$display$$\begin{equation} F = \frac{1}{2} w^T Qw+b^T w ~~~~~~~~~~~~~(9) \end{equation}$$display$$

С заданными ограничениями
1) l ≤ w ≤ u;
2) Cw * d;
где w, l, u, d, b – n-мерные действительнозначные векторы, Q – симметричная матрица квадратичной части, а знак * означает любое из отношений ≥=≤.
Как видно из (8) линейная часть bTw в нашей целевой функции равна нулю. Однако матрица А не является симметричной, что, впрочем, не мешает привести её к симметричному виду, не изменяя самой функции. Для этого достаточно положить вместо A выражение $inline$\begin{equation}\frac{A^T+A}{2}\end{equation}$inline$.Так как в формулу (9) входит коэффициент $inline$\frac{1}{2}$inline$, то мы в качестве Q мы можем принять $inline$A^T+A$inline$.

Координаты векторов l и u задают границы изменения искомого вектора и лежат в диапазоне [-1,1]. Так как мы не предполагаем коротких продаж облигаций, то координаты векторов в нашем случае все не меньше 0. В приведенном ниже примере программы, для простоты, вектор l принят равным нулю, а коэффициенты вектора u все равны 0,3. Ничто, впрочем, не мешает усовершенствовать программу и сделать вектора ограничений более настраиваемыми.

Матрица С в нашем случае будет состоять из двух строк: 1) коэффициенты дисконтирования, которые при скалярном умножении на веса (то самое (w,k)) должны давать целевую ставку доходности портфеля; 2) строка, состоящая из единиц. Она нужна для задания ограничения $inline$\sum_{i}w_i=1$inline$.

Таким образом, выражение Cw*d для нашей задачи будет выглядеть так:

$$display$$\begin{equation} \left\{\begin{array}{ccc} ({\bf w,k}) = k_p \\ \sum_{i}w_i = 1 \\ \end{array} \right. ~~~~~~~~~~~~~(10) \end{equation}$$display$$


Перейдем теперь к программной реализации поиска оптимального портфеля. Основу квадратичного оптимизатора в ALGLIB составляет объект $inline$\tt \small minqpstate$inline$
alglib::minqpstate state;

Для инициализации оптимизатора этот объект передается функции minqpcreate вместе с параметром размерности задачи n
alglib::minqpcreate(n, state);

Следующим важнейшим моментом является выбор алгоритма оптимизации (солвера). Библиотека ALGLIB для квадратичной оптимизации предлагает три солвера:
  • QP-BLEIC – наиболее универсальный алгоритм, предназначенный для решения задач с не очень большим (до 50 по рекомендациям документации) числом линейных ограничений (вида Cw*d). Может при этом быть эффективным на задачах большой размерности (как утверждает документация – до n=10000).
  • QuickQP – очень эффективный алгоритм, особенно когда оптимизируется выпуклая функция. Однако, к сожалению, не может работать с линейными ограничениями – только с граничными условиями (вида l≤w≤u).
  • Dense-AUL – оптимизирован для случая очень больших размерностей и большого количества ограничений. Но, по утверждению документации, задачи небольшой размерности и числа ограничений будут эффективней решаться с помощью других алгоритмов.

С учетом приведенных характеристик, очевидно, что для нашей задачи наиболее подходит солвер QP-BLEIC.

Для того, чтобы дать указание оптимизатору использовать данный алгоритм необходимо вызвать функцию $inline$\tt \small minqpsetalgobleic$inline$. Этой функции передаются сам объект и критерии остановки, на которых мы не будем подробнее останавливаться: в рассматриваемой здесь программе используются значения по-умолчанию. Вызов функции выглядит следующим образом:

alglib::minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);

Дальнейшая инициализация солвера включает:
  • Передачу матрицы квадратичной части Q$inline$\tt \small alglib::minqpsetquadraticterm(state, qpma);$inline$
  • Передачу вектора линейной части (в нашем случае – нулевого вектора) – $inline$\tt \small alglib::minqpsetlinearterm(state, b);$inline$
  • Передачу векторов граничных условий l и u$inline$\tt \small alglib::minqpsetbc(state, bndl, bndu);$inline$
  • Передачу линейных ограничений – $inline$\tt \small alglib::minqpsetlc(state, c, ct);$inline$
  • Настройку масштаба координат векторного пространства $inline$\tt \small alglib::minqpsetscale(state, s);$inline$

Остановимся подробней на каждом пункте:
Для задания векторов и матриц в библиотеке ALGLIB применяются объекты специальных типов (целых и действительнозначных): $inline$\tt \small alglib::integer\_1d\_array$inline$, $inline$\tt \small alglib::real\_1d\_array$inline$, $inline$\tt \small alglib::integer\_2d\_array$inline$, $inline$ \tt \small alglib::real\_2d\_array$inline$. Для подготовки матрицы нам необходим тип $inline$\tt \small real\_2d\_array$inline$. В программе сначала создадим матрицу А ($inline$\tt \small alglib::real\_2d\_array~ qpma$inline$), а затем по формуле $inline$Q=A^T+A$inline$ из нее построим матрицу Q ($inline$\tt \small alglib::real\_2d\_array~ qpmq$inline$). Задание размерности матриц в ALGLIB производится отдельной функцией $inline$\tt \small setlength(n,m)$inline$.

Для построения матриц нам понадобятся вектора коэффициентов дисконтирования (ki) и отношения дюрации к этим коэффициентам ($inline$\frac{D_j}{k_j}$inline$):

std::vector<float> disfactor; 
std::vector<float> durperytm;

Фрагмент кода, реализующий построение матриц приведен в следующем листинге:
size_t n = durations.size();

alglib::real_2d_array qpma; qpma.setlength(n,n); // matrix nxn
alglib::real_2d_array qpmq; qpmq.setlength(n,n); // matrix nxn

for(size_t j=0; j < n; j++) 
{
    for (size_t i = 0; i < n; i++) qpma(i,j) = durperytm[j]*disfactor[i];  //i,j элемент матрицы
}

for(size_t j=0; j < n; j++) 
{
    for (size_t i = 0; i < n; i++) qpmq(i,j) = qpma(i,j) + qpma(j,i);
}

Вектор линейной части, как уже было указано, в нашем случае нулевой, поэтому с ним всё просто:
alglib::real_1d_array b; 
b.setlength(n);
for (size_t i = 0; i < n; i++) b[i] = 0;

Вектора граничных условий передаются одной функцией. Для решения рассматриваемой задачи применяются очень простые граничные условия: веса каждой бумаги не должны быть меньше нуля (мы не допускаем отрицательные позиции) и не должны превышать 30%. При желании ограничения можно усложнить. Эксперименты с программой показали, что даже простое изменение данного диапазона может сильно повлиять на результаты. Так, увеличение нижней границы и/или снижение верхней приводит к большей диверсификации итогового портфеля, ибо при оптимизации солвер может некоторые бумаги исключить из результирующего вектора (присвоить им вес 0%) как не подходящие. Если задать нижнюю границу весов, скажем, в 5%, то все бумаги гарантировано войдут в портфель. Однако расчетная дюрация при таких настройках будет, разумеется, больше, чем в случае, когда оптимизатор может исключать бумаги.

Итак, граничные условия задаются двумя векторами и передаются солверу:

alglib::real_1d_array bndl; bndl.setlength(n); 
for (size_t i = 0; i < n; i++) bndl[i] = 0.0; // low boundary
alglib::real_1d_array bndu; bndu.setlength(n); 
for (size_t i = 0; i < n; i++) bndu[i] = 0.3;// high boundary

alglib::minqpsetbc(state, bndl, bndu);

Далее оптимизатору необходимо передать линейные ограничения, задаваемые системой (10). В ALGLIB это делается с помощью функции $inline$\tt \small alglib::minqpsetlc(state, c, ct)$inline$, где с – это матрица, объединяющая левую и правую части системы (10), т.е. матрица вида $inline$(C ~~ d)$inline$, а ct – вектор отношений (т.е. соответствий вида ≥, = или ≤). В нашем случае ct = (0,0), что соответствует отношению '=' для обеих строк системы (10).

for (size_t i = 0; i < n; i++)
{
   c(0,i) = disfactor[i]; //первая строка системы - коэффициенты дисконтирования облигаций
   c(1,i) = 1;  //вторая строка системы – единичная – для суммы весов
}
c(0,n) = target_rate; // первая строка (правая часть) – целевая доходность портфеля
c(1,n) = 1; // вторая строка (правая часть) – сумма весов, равная единице
alglib::integer_1d_array ct = "[0,0]"; // вектор отношений
alglib::minqpsetlc(state, c, ct);

Документация к библиотеке ALGLIB очень рекомендует задавать масштаб переменных перед запуском оптимизатора. Это особенно важно, если переменные измеряются в единицах, изменение которых отличается на порядки (например, при поиске решения, тонны могут изменяться в сотых или тысячных долях, а метры в единицах; задача при этом может решаться в пространстве «тонна-метр»), что влияет на критерии оставки. Есть, впрочем, оговорка, что при одинаковом шкалировании переменных, задание масштаба не обязательно. В рассматриваемой программе мы все же проводим задание масштаба ради большей строгости подхода, тем более, что сделать это очень просто.
alglib::real_1d_array s; 
s.setlength(n); 
for (size_t i = 0; i < n; i++) s[i] = 1; // масштаб всех переменных одинаков
alglib::minqpsetscale(state, s);

Далее зададим оптимизатору начальную точку. Вообще, этот шаг тоже не является обязательным, и программа благополучно справляется с поставленной задачей без заданной явно начальной точки. Аналогично, из соображений строгости начальную точку зададим. Мудрить не будем: начальной точкой будет являться точка с одинаковыми весами для всех облигаций.
alglib::real_1d_array x0; 
x0.setlength(n); 
double sp = 1/n; 
for (size_t i = 0; i < n; i++) x0[i] = sp;
alglib::minqpsetstartingpoint(state, x0);

Остается определить переменную, в которую оптимизатор вернет найденное решение и переменную статуса. После чего можно запускать оптимизацию и обрабатывать результат
alglib::real_1d_array x;  // результирующая точка
alglib::minqpreport rep;  // статус

alglib::minqpoptimize(state); // запуск оптимизатора
alglib::minqpresults(state, x, rep); // получение статуса расчетов и результата

alglib::ae_int_t tt = rep.terminationtype;
if (tt>=0) // проверка на завершение оптимизации без ошибок
{
      std::cout << "Веса облигаций в портфеле:" << '\n';
      for(size_t i = 0; i < n; i++) // Выводим список облигаций с рассчитанными весами
      {
        std::cout << (i+1) << ".\t" << bonds[i].bondname << ":\t\t\t " << (x(i)*100) << "\%" << std::endl;
      }

      for (size_t i = 0; i < n; i++)
      {
        for (size_t j = 0; j < n; j++)
        {
          qpmq(i,j) /= 2;
        }
      }
}

Специально время работы программы в проводимых экспериментах не измерялось, но всё работает очень быстро. При этом, понятно, что частный инвестор вряд ли будет оптимизировать портфель более чем из 10-15 облигаций.

Важно еще заметить следующее. Оптимизатор возвращает именно вектор весов. Чтобы получить саму расчетную дюрацию необходимо непосредственно воспользоваться формулой (8). Программа умеет это делать. Для этого специально были добавлены две функции перемножения векторов и матриц. Здесь их приводить не будем. Желающие сами без труда найдут их в опубликованных исходных кодах.

На этом всё. Всем эффективных инвестиций в долговые инструменты.

P.S. Понимая, что ковыряния в чужом коде, занятие не самое привлекательное, а для многих людей, желающих заниматься инвестированием, и вовсе не профильное, постараюсь чуть позже переложить эту программу в форму простого веб-сервиса, которым смогут пользоваться все желающие независимо от знания математики и программирования.

Let's block ads! (Why?)

История стартапа: как пошагово разработать идею, выйти на несуществующий рынок и дойти до международной экспансии

Привет, Хабр! Не так давно мне удалось поговорить с Николаем Вакориным – основателя интересного проекта Gmoji – это сервис для отправки офлайн-подарков с помощью эмоджи. В ходе разговора Николай делился своим опытом разработки идеи для стартапа с опорой на выработанные критерии, привлечении инвестиций, масштабировании продукта и сложностях на этом пути. Передаю ему слово.

Подготовительная работа


Я довольно давно занимаюсь бизнесом, но раньше это все больше были офлайн-проекты в сфере ретейла. Такой бизнес очень изматывает, я устал от постоянных сложностей, часто внезапных и бесконечных.

Поэтому, продав очередной проект в 2012 году, я немного отдохнул и начал думать, чем заняться дальше. Новый, пока еще не придуманный проект, должен был соответствовать таким критериям:

  • никаких физических активов, которые надо покупать и тратить деньги на их поддержку и которые легко из активов превращаются в пассивы, если что-то идет не так (пример: оборудование для ресторана, который закрывается);
  • отсутствие дебиторской задолженности. Почти всегда в моих предыдущих проектах складывалась ситуация, при которой заказчики требовали постоплату, а поставку услуг и товаров – сразу. Понятно, что потом приходилось просто выбивать свои деньги и тратить на это много времени и сил, иногда решить задачу не удавалось (или удавалось частично);
  • возможность работать с небольшой командой. В офлайн-бизнесе одна из главных проблем – это наем сотрудников. Как правило, их трудно искать и мотивировать, текучесть высока, люди работают не очень хорошо, часто воруют, на контроль нужно тратить много ресурсов;
  • возможность роста капитализации. Потенциал роста офлайн-проекта всегда ограничен, а я хотел попробовать замахнуться на мировой рынок (хоть пока и не понимал как);
  • наличие стратегии выхода. Хотелось получить такой бизнес, который был бы ликвиден и из которого я мог бы легко и быстро выйти в случае необходимости.

Очевидно, что это должен был быть какой-то онлайн-стартап и что в одиночку перейти от критериев непосредственно к идее будет тяжело. Поэтому я собрал группу единомышленников – бывших партнеров и коллег, – которым могло быть интересно поработать над новым проектом. У нас получился некий бизнес-клуб, который периодически собирался для обсуждения новых идей. На такие встречи и мозговые штормы ушло несколько месяцев.

В результате у нас появилось несколько неплохо выглядевших бизнес-идей. Для того чтобы выбрать одну, мы решили, что автор каждой идеи проведет презентацию своего концепта. «Защита» должна была включать в себя бизнес-план и какой-то алгоритм действий на несколько лет.

На этом этапе у меня родилась идея «социальной сети с подарками». По итогам обсуждений именно она победила.

Какие проблемы мы хотели решить


На тот момент (2013 год) существовало три нерешенные проблемы, связанные со сферой подарков:
  • «не знаю, что подарить»;
  • «не знаю, куда девать ненужные подарки и как перестать их получать»;
  • «непонятно, как быстро и без проблем отправить подарок в другой город или страну».

Решений тогда не было. Первую проблему хотя бы пытались решить различные сайты с рекомендациями, но работало это неэффективно. Во многом потому, что почти все такие подборки были плохо скрытой рекламой определенных товаров.

Вторую проблему в целом можно было бы решить составлением вишлистов – это популярная на Западе практика, когда, например, накануне дня рождения именинник пишет список подарков, которые хотел бы получить, а гости выбирают, что купят, и сообщают о своем выборе. Но в России эта традиция не особенно прижилась. С доставкой же подарков ситуация была и вовсе плачевная: отправить что-то в другой город или тем более страну без множества телодвижений было невозможно.

Было ясно, что в теории мы можем сделать что-то полезное для решения этих проблем. Но рынок во многом предстояло формировать самостоятельно, да еще и ни у одного из членов команды не было технического бэкграунда.

Поэтому для начала мы взяли бумагу и карандаш и начали разрабатывать мокапы экранов будущего приложения. Это позволило нам понять, что на первое место нам стоит поставить третью проблему из списка – доставку подарков. И в процессе обсуждений того, как это можно реализовать, родилась идея использовать эмоджи для представления подарков, которые один человек мог бы отправить онлайн, а другой – получить офлайн (например, чашку кофе).

Первые трудности


Поскольку у нас не было опыта работы над ИТ-продуктами, все двигалось довольно медленно. Мы потратили много времени и денег на разработку прототипа. Настолько много, что некоторые участники первоначальной команды начали терять веру в проект и выходить из него.

Тем не менее мы смогли создать продукт. Также благодаря хорошей сети контактов в нашем городе – Екатеринбурге – нам удалось в тестовом режиме подключить к платформе около 70 бизнесов. В основном это были кофейни, цветочные магазины, автомойки и т. п. Пользователи могли оплатить какой-то подарок, вроде чашки кофе, и отправить его кому-то. Получатель затем должен был прийти в нужное место и получить свой кофе бесплатно.

Оказалось, что все выглядит гладко только на бумаге. На практике же огромной проблемой стало непонимание со стороны сотрудников организаций – наших партнеров. В условном кафе текучесть крайне велика, а обучению часто не уделяют достаточно времени. В итоге менеджеры заведения могли просто не знать, что оно подключено к нашей платформе, и затем отказывались выдавать уже оплаченные подарки.

Конечные пользователи тоже не до конца понимали продукт. Например, нам казалось, что мы сумели создать идеальную систему стандартизации подарков. Ее суть была в том, что конкретный gmoji для отображения подарка был связан с классом товаров, а не компанией-поставщиком. То есть когда пользователь отправлял в подарок чашку капучино, адресат мог получить свой кофе в любом заведении, подключенном к платформе. При этом в разных местах цена чашки варьируется – и пользователи не понимали, что это вообще не их проблема и они могут пойти в любое место.

Объяснить аудитории нашу задумку не удалось, поэтому по многим товарам в итоге мы все же переключились на связку «gmoji – конкретный поставщик». Теперь часто подарок, купленный через конкретный gmoji, можно получить только в магазинах и заведениях той сети, которая привязана к этому символу.

Трудно было и расширять количество партнеров. Крупным сетям было сложно объяснить ценность продукта, переговоры шли тяжело и долго, а результата по большей части не было.

Поиск новых точек роста


Мы экспериментировали с продуктом – например, сделали не просто приложение, а мобильную клавиатуру, с помощью которой отправлять подарки стало можно в любом чат-приложении. Выходили в новые города – в частности, запустились в Москве. Но все равно темпы роста были не особенно впечатляющими. На все это ушло несколько лет, мы по-прежнему развивались на собственные средства.

К 2018 году стало ясно, что нам нужно ускоряться – и для этого нужны деньги. Обращаться в фонды и акселераторы с продуктом для все еще не сформированного рынка нам показалось не очень перспективно, вместо этого я привлек в качестве инвестора бывшего партнера по одному из прошлых проектов. Нам удалось привлечь $3,3 млн инвестиций. Это позволило нам смелее отрабатывать различные маркетинговые гипотезы и активнее заниматься экспансией.

Эта работа дала возможность понять, что мы упускаем кое-что важное, а именно корпоративный сегмент. Компании во всем мире активно дарят подарки – партнерам, клиентам, сотрудникам и т. п. Процесс подготовки таких закупок часто непрозрачен, в нем множество посредников, у бизнеса обычно нет контроля над доставкой.

Мы подумали, что проект Gmoji мог бы решить эти проблемы. Во-первых, с доставкой – ведь адресат сам идет получать свой подарок. К тому же, поскольку доставка сначала идет в цифровом виде, изображение подарка можно кастомизировать, брендировать, даже запланировать – например, прямо перед новым годом, в 23:59, прислать оповещение с emoji-подарком от компании. Также у компании появляется больше данных и контроля: кто, где и когда получил подарок и т. п.

В итоге привлеченные деньги мы использовали для разработки B2B-платформы отправки подарков. Это маркетплейс, где поставщики могут предлагать свои товары, а компании – покупать их, брендировать с помощью эмоджи и отправлять.

В результате нам удалось привлечь крупных заказчиков. К примеру, на нас вышли несколько компаний – и мы смогли отработать некоторые интересные кейсы в программах повышения корпоративной лояльности и рассылки корпоративных подарков, в том числе через push-уведомления сторонних мобильных приложений.

Новый поворот: международная экспансия


Как видно из текста выше, наше развитие шло постепенно и к выходу на зарубежные рынки мы только присматривались. В какой-то момент, когда проект уже стал заметен на родине, мы начали получать запросы от предпринимателей из других стран о покупке франшизы.

На первый взгляд идея казалась странной: на свете мало ИТ-стартапов, масштабирующихся по модели франшизы. Но запросы продолжали поступать, поэтому мы решили попробовать. Так проект Gmoji вышел в две страны бывшего СССР. И как показала практика, такая модель для нас оказалась рабочей. Мы «упаковали» нашу франшизу, чтобы начать работу можно было быстро. В результате к концу этого года число поддерживаемых стран вырастет до шести, а к 2021 году мы планируем присутствовать в 50 странах – и активно ищем партнеров для этого.

Заключение


Проекту Gmoji уже около семи лет. За это время мы столкнулись с большим количеством трудностей и усвоили ряд уроков. В заключение перечислим их:
  • Работа над идеей стартапа – это процесс. Мы очень долго оттачивали идею проекта, начав с базовых критериев, перешли к отбору возможных направлений, каждое из которых серьезно анализировали. И даже после окончательного выбора менялись подходы к определению целевой аудитории и работе с ней.
  • Новые рынки – это очень трудно. Несмотря на то что на еще не сформированном рынке есть шанс заработать много и стать лидером, это очень трудно, потому что люди не всегда понимают ваши гениальные задумки. Поэтому не стоит ждать быстрого успеха и готовиться много и тяжело работать над продуктом, постоянно общаться с аудиторией.
  • Важно анализировать сигналы рынка. Если какая-то идея кажется неудачной, это не повод не проанализировать ее. Так было с идеей масштабирования через франшизы: сначала идея «не зашла», но в итоге мы получили и новый канал прибыли, и вышли на новые рынки, и привлекли десятки тысяч новых пользователей. Потому что в конце концов прислушались к рынку, который сигнализировал о востребованности идеи.

На сегодня всё, спасибо за внимание! Буду рад ответить на вопросы в комментариях.

Let's block ads! (Why?)

Литература на выходные: легкое чтение для технарей

Летом мы публиковали подборку книг, в которой не было справочников или руководств по алгоритмам. Она состояла из литературы для чтения в свободное время — для расширения кругозора. В качестве продолжения мы подобрали научную фантастику, книги о технологическом будущем человечества и другие издания, написанные специалистами для специалистов.


Фото: Chris Benson / Unsplash.com


Наука и технологии


«Квантовые вычисления со времен Демокрита»

Книга рассказывает, как развивались глубокие идеи математики, компьютерных наук и физики. Её написал специалист по теории вычислительных машин и систем Скотт Ааронсон (Scott Aaronson). Он работает преподавателем факультета компьютерных наук в Техасском университете (к слову, некоторые лекции автора опубликованы в его блоге). Экскурс Скотт начинает со времен Древней Греции — с работ Демокрита, который говорил об «атоме», как о неделимой частице вещества, обладающей истинным бытием. Затем он плавно переводит повествование к развитию теории множеств и вычислительной сложности, а также квантовым компьютерам и криптографии.

Еще книга затрагивает и такие темы, как путешествия во времени и парадокс Ньюкома. Поэтому она может быть полезна и интересна не только любителям физики, но и тем, кто увлекается мысленными экспериментами и занимательными задачками.

Soonish: Ten Emerging Technologies That'll Improve and / or Ruin Everything

Это — лучшая научная книга 2017 года по версии Wall Street Journal и Popular Science. Келли Вайнерсмит (Kelly Weinersmith), ведущая подкаста о науке и связанных с ней вещах «Science… sort of», говорит про технологии, которые станут частью нашей жизни уже в обозримом будущем.

Это — 3D-принтеры для печати еды, автономные роботы и микрочипы, встраиваемые в тело человека. Повествование Келли строит на основе встреч с учеными и инженерами. С толикой юмора она рассказывает, почему эти проекты нужны, и что мешает их развитию.

Chasing New Horizons: Inside the Epic First Mission to Pluto

14 июля 2015 года состоялось знаменательное событие. Межпланетная станция New Horizons успешно добралась до Плутона и сделала несколько фотографий в высоком разрешении. Однако не все знают, что миссия много раз висела на волоске, и её успех — практически чудо. Эта книга — история полета New Horizons, рассказанная и написанная участниками событий. Руководитель научной программы NASA Алан Штерн (Alan Stern) и астробиолог Дэвид Гринспун (David Greenspoon) описывают трудности, с которыми сталкиваются инженеры в процессе проектирования, сборки и запуска космических аппаратов — рассказывают о работе без права на ошибку.
Soft skills и работа мозга


Factfulness: Ten Reasons We're Wrong About the World

Примерно 90% людей на планете уверены, что ситуация в мире только ухудшается. Они ошибаются. Специалист по статистике Ханс Рослинг (Hans Rosling) в своей книге доказывает, что за последние 20 лет люди стали жить лучше. Причину, по которой восприятие обывателя отличается от реального положения дел, Рослинг видит в неумении обращаться с информацией и фактами. В 2018 году Билл Гейтс внес «Factfulness» в личный список литературы, обязательной к прочтению, и даже подготовил краткое резюме по книге в формате видеоролика.


Moonshot: What Landing a Man on the Moon Teaches Us About Collaboration

Профессор Ричард Уайзман (Richard Wiseman), член комитета скептических расследований, рассуждает о составляющих успешной работы в команде на основе интервью с сотрудниками центра управления полетами, которые запускали «Аполлон-11». В книге можно найти не только размышления о том, «как надо», но и узнать некоторые детали космической миссии.
The Second Kind of Impossible: The Extraordinary Quest for a New Form of Matter

Это — автобиография американского физика-теоретика Пола Стейнхардта (Paul Steinhardt). Он описывает результаты своей 35-летней охоты за квазикристаллами. Это твердые тела, которые состоят из атомов, не образующих кристаллическую решетку. Пол с коллегами путешествовал по миру, стремясь доказать, что такие материалы можно найти в природе, а не только синтезировать. Кульминация истории наступает на Камчатском полуострове, где ученым все же удается обнаружить кусочки метеорита с квазикристаллами. В этом году книгу номинировали на приз британского Королевского общества за вклад в развитие научно-популярной литературы.


Фото: Marc-Olivier Jodoin / Unsplash.com

How To: Absurd Scientific Advice for Common Real-World Problems

Любую задачу можно решить правильно или неправильно. Рэндел Манро (Randall Munroe) — инженер НАСА, а также художник серии комиксов xckd и книги «А что, если?» — говорит, что есть третий способ. Он подразумевает невероятно сложный и нерациональный подход, которым никто и никогда не будет пользоваться. Манро приводит примеры именно таких подходов — для самых разных кейсов: от копания ямы до посадки самолета. Но автор стремится не просто развлечь читателя, с помощью гипербол он показывает, как устроены популярные технологии.
Художественная литература


The Fifth Science

Спекулятивная фантастика от exurb1a — основателя образовательного YouTube-канала с 1,5 млн подписчиков. Книга представляет собой сборник из 12 историй об основании, расцвете и падении Галактической империи людей. Автор говорит о науках, технологиях и человеческих поступках, которые неминуемо ведут к гибели цивилизации. The Fifth Science рекомендуют многие резиденты Reddit. Книга должна понравиться тем, кто оценил цикл «Основание» Айзека Азимова.
How to Invent Everything: A Survival Guide for the Stranded Time Traveler

Что делать, если ваша машина времени сломалась, и вы застряли в далеком прошлом? Как выжить? И можно ли ускорить развитие человечества? Ответы на эти вопросы дает книга. Её написал Райан Норт (Ryan North) — разработчик программного обеспечения и художник Dinosaur Comics.

Под обложкой скрывается своеобразное руководство по сборке устройств, которыми мы пользуемся сегодня — например, компьютеров, самолетов, сельскохозяйственных машин. Все это снабжено картинками, схемами, научными выкладками и фактами. В National Public Radio назвали How to Invent Everything лучшей книгой 2018 года. Положительно о ней отозвался и Рэндел Манро. Он окрестил работу Норта must-have'ом «для тех, кто желает быстро построить индустриальную цивилизацию».



Наше — на Хабре:

Let's block ads! (Why?)

[Из песочницы] Недовнедренная ERP в производстве: в реанимацию или в морг?

Как превратить условно-работающую ERP в реальный инструмент управления производством и поставками.

Питеркин Сергей, Меркулов Михаил, «Райтстеп»

За последние годы, количество производственных предприятий, заявляющих о внедренных ERPсистемах, значительно возросло. И составляет уже не десятки, а сотни. Говорим мы прежде всего о дискретном производстве, а под «производственной ERP» подразумеваем любую систему, претендующую на это гордое название. По частоте наших «столкновений», наиболее распространенными «работающими в производстве» ERP являются — BaaN/InforLN, InforERPSyteLine, постоянно-растущая «армия» заводов с 1С, и в небольшом количестве SAPERP и прочая экзотика.

Данная статься будет интересна прежде всего «продвинутым» пользователям ERP, в большей степени с позаказным типом производства («вытягивание» под заказ или на склад, в т.ч. и «вытягивание» под прогноз спроса), тем, кто автоматизировал (возможно – «как есть») процессы учета хода производства, т.е. формирования производственных заданий (далее по тексту – ПЗ. В разных системах: SFC-заказы, Job-Orders, JOBs, Заказы на Производство, Производственные заказы и т.п.) и их отслеживания, но так и не смог уверенно производство (и поставки – МТО (Материально-Техническое Обеспечение)) планировать, как и не смог поставить мониторинг производства, в т.ч. и позаказный. С непрекращающимися попытками все-же запустить планирование, и/или с попытками обеспечить планирование с использованием волшебных алгоритмов и/или систем типа APS, MES.

В силу ограниченности объема статьи мы не будет останавливаться на разборе того, почему «традиционные» ERP плохо внедряются и/или работают И для планирования И для управления производством, а также на разборе того, почему «магия» APS или MESсистем превращается на большинстве наших заводов в шарлатанство. Цель статьи – показать, как определенной категории предприятий, которые узнают себя в написанном ниже, построить замкнутую систему планирования/мониторинга не на обломках, но с использованием того, что есть сейчас.

Уверены, что настоящая статья будет интересна также и заводам или холдингам, только стоящим перед выбором системы или в начале проекта внедрения. Т.к. поможет избежать традиционных ошибок, наблюдаемых нами на протяжении последних примерно 8 лет.


Постановка задачи для типичного позаказного производственного бизнеса


Типичные жалобы, следствия и причины


  1. «Счетные» бизнес-проблемы предприятия.
    • Неуправляемые срывы сроков выполнения заказов, в особенности, в условиях частных изменений заказов (прием новых, изменение существующих) --> потеря оборота.
    • Увеличенные (высокие, относительно прибыли) трудозатраты на администрирование производства, авральные работы --> увеличенные издержки.
    • Неоптимальный (высокий, относительно оборота) объем НзП (Незавершенное производство)
      увеличенные издержки, увеличенные циклы, потеря пропускной способности (недостаточная пропускная способность) производства.
  2. Являются следствием….
    • Невозможности надежного «прогнозирования» (должно быть — расчета плановых/расчетных дат) сроков выполнения заказов клиентов.
    • Отсутствия информации о существующих и будущих (по всему циклу производства) проблемах в выполнении заказа.
    • Неоптимальной загрузки узких мест (обрабатывают не то, не в то время, не в той последовательности).
  3. Являются следствиями следующих (некорневых!) причин.
    • Отсутствие формализованной системы быстрого <позаказного> планирования:
      1) с учетом загрузки узких мест (очередь обработки составляющих заказа);
      2) с учетом приоритетов заказов.
    • Отсутствие прослеживаемости и визуализации состояния заказа(ов) по всей производственной цепочке.

Цель


  1. Надежное определение сроков выполнения заказа – для разовых и срочных заказов. С учетом циклов производства/закупки (по критическим «веткам» состава изделиязаказа) и с учетомсвободных запасов (материалов, ПКИ (покупных комплектующих изделий), НзП) и ожидаемых приходов по ЗП (заказы поставщикам) и ПЗ.
  2. Минимизация средневзвешенных срывов сроков для «долгосрочных заказов»:
    1. через общую балансировку выпуска,
    2. через приоретизированный план производства и исполнение,
    3. через контроль исполнения плана с визуализацией отклонений от сроков.
  3. Максимально-эффективная загрузка узких мест.

Типичная модель планирования типичного завода с недовнедренной «производственной ERP»


Общее описание


  1. В настоящее время для управления производством и поставками используется «производственная ERP».
  2. Управление МТО, Учет хода производства, Управление запасами, в т.ч. производственными – очень часто сделаны на хорошем уровне.
  3. При этом, Планирование реализовано частично, с использованием не предназначенных для этого функций системы и/или — самостоятельных разработок.
    • Планирование выпуска («Верхний» уровень планирования – формирование Основного Производственного Плана). Никак не реализовано, или реализовано в MS-Excel. Без привязки к модели и параметрам реального производства. Без учета существующего состояния производства:
      1) выполняемых или запланированных к запуску ПЗ/ЗП,
      2) запасов ПКИ, материалов и НзП, в разных статусах «закрепления» (распределения) за заказами клиентов,
      3) свободных/ожидаемых запасов готовых изделий, выпускаемых «на склад» (под прогноз спроса или точку перезаказа),
      4) с учетом ресурсной модели (ресурс = специальность), но без необходимой детализации.
    • Планирование производства (Уровень планирования — Синхронизированное Планирование Производства и Поставок).

      1) Планирование производства реализовано через создание производственных заданий (объектов управления исполнением!) по всей структуре изделия заказа и расчета дат запуска-выпуска методом простейшего сетевого планирования (конец работ — цикл производства = начало. = конец входящего компонента — …). Такой подход не обеспечивает необходимой для достижения указанных выше целей информации и имеет массу недостатков (см.ниже), в силу чего для реального планирования и управления производством практически не используется. Производство управляется «вручную», ПЗ используются только для учета!

      2) Поставки (МТО) планируются под сформированные ПЗ. Точность такого плана = точности планирования ПЗ, т.е. – достаточно низкая. Но т.к. «позаказные составы изделия» (или — «цепочка ПЗ») заведомо растянуты и не учитывают существующих запасов, МТО почти всегда удается не допускать дефицитов производства. В отсутствии системы планирования, которая постоянно учитывает внутренние (производство, МТО, запасы) и внешние (заказы, прогнозы) изменения, это достигается, очевидно, завышенными запасами материалов и ПКИ.


Детальный разбор используемой модели планирования


Модель планирования

image


  1. Объекты управления исполнением (Производственные задания ПЗ) используются не по назначению — не для управления исполнением, но для созданияПроизводственного (позаказного) Состава Изделия (ПСИ), а также — для позаказного планирования (попытки планирования). При отсутствии в ИТ-системе функций <сквозного> позаказного планирования и позаказного состава это становится единственным вариантом, позволяющим <хоть как-то> управлять всей цепочкой выполнения заказа клиента (ЗК). Такой подход имеет следующие принципиальные недостатки.
    • ПСИ, созданный с использованием объектов исполнения — фиксированный. Изменения, возникающие, например, в КСИ/ТСИ (Конструкторский/Технологический составы) из-за конструкторско-технологических изменений, могут учитываться только вручную. На практике, при большом объеме объектов управления это означает: <никак>. Как результат — ошибки в планах, решаемые только через трудоемкое и неэффективное ручное управление.
    • ПЗ, по определению, плохо обрабатываются планировщиками 2го уровня производственного планирования (планировщики-синхронизаторы, APSPlanner'ы и даже MRP, в т.ч. <позаказные> — см. ниже). В т.ч. потому, что для планировщика ПЗ — это фиксированные ожидаемые приходы, а не рассчитываемые планировщиком гибкие <элементы> ПСИ(плановые заказы, pln).
    • При планировании ПСИ, смоделированного на основании ПЗ, не учитываются запасы и ожидаемые приходы ДСЕ, которые могут быть использованы для выполнения данного заказа, в соответствии с правилами распределения/разметки запасов/ожидаемых приходов.
  2. Планирование выполняется через алгоритм собственной разработки, в одну итерацию, с разузлованием состава, определением потребных количеств брутто (!) и смещением влево дат начала ПЗ. При этом используется имеющийся ограниченный набор времен пооперационной модели (пооперационный маршрут), для операций которой (модели), как правило, не определены необходимые для планирования времена, типа <время до>, <время после>, <буфер до>, <буфер после>, <время очереди>, <время перемещения> и т.п. Это приводит к большим и трудно управляемым погрешностям рассчитываемых сроков.
  3. Под спланированные ПЗ через стандартный алгоритм планирования рассчитываются потребности в закупаемых материалах и ПКИ, формируются объекты управления — ожидаемые приходы, ЗП.

В идеальных условиях такая модель могла бы работать. В условиях же постоянных внутренних и внешних изменений реального мира она очень быстро становится неустойчивой.


Критическая проблема №1

image

image

В случае наличия запаса в производстве или ожидаемого прихода ДСЕ, которые могут быть использованы для выполнения заказа (что вполне может случится из-за изменений в ПСИ другого заказа, изменений приоритетов/дат заказов и многих других причин), — потребности производства и закупок принципиально меняются — см. пример на рисунках выше. Прежний <жестко-позаказно-идеальный> план может быть изменен только вручную (реально, для сотен и тысяч объектов управления — ПЗ, это крайне затруднительно и не выполняется). Это приводит к перезакупке материалов и ПКИ, а в итоге — к <замораживанию> оборотки, потенциальным неликвидам, и перепроизводству. Если с перезакупкой плохо, но как-то еще можно жить (если нет проблем с обороткой:) — т.к. <пойдет на другие заказы:>, то производство <ненужных> <сейчас> ДСЕ, особенно в узких местах, отнимает драгоценные <рубле-часы> всего оборота завода. Как результат — уменьшение оборота, прибыли (в т.ч. за счет доп.расходов на авралы), срывы сроков заказов. Как итог — потеря/неувеличение доли рынка.

Еще одна проблема использования такого простейшего планирования — фактическое отсутствие реакции на происходящее в производстве/закупках. Неправильное определение или даже потеря приоритетов ЗК в <черном ящике> производства. Даже и прежде всего при определении очередности обработки заказов (частей <изделия>заказа) в УМ (узких местах).


Критическая проблема №2


  1. Допустим, первоначальное планирование (это маловероятно с использованием только 2го уровня планирования, но теоретически возможно) обеспечивает квази-оптимальную (близкую к оптимальной) загрузку узкого места.

image


  1. Однако, отсутствие быстрого и частого перепланирования по всей цепочке выполнения заказа (ресинхронизация) не позволяет учесть такие типичные для реального производства ситуации, как: неустранимый срыв сроков производства/закупки каких-либо комплектующих, изменение приоритетов/дат заказов или их остановка, изменение ТСИ и т.п.
  2. Как показано в примере ниже, неустранимый срыв сроков заказа ХХ ведет к переносу сроков его готовности и отгрузки. При этом, при отсутствии системы ресинхронизации, узкое место потеряет время на обработку ДСЕ этого заказа, которые могли бы и должны быть обработаны позже. При наличии новых или срочных заказов, или заказов с устранимыми срывами срока, УМ не сможет обрабатывать их детали, т.к., скорее всего, никто не покажет данному участку правильную последовательность/приоритеты обработки! Как результат — меньший, чем мог бы быть выпуск (готовых изделий), потеря оборота и прибыли.

image


Критическая проблема №3

Планирование с консолидацией. Планирование с консолидацией производимых ДСЕ, при работе с узкими местами в производственно-логистической цепочке выполнения заказа, также ведет к неправильному использованию времени узкого места. Что, опять же, ведет к потере/недополучении оборота/прибыли.


  1. Планирование с позаказной загрузкой узкого места.

image


  1. Планирование с консолидацией выпускаемых ДСЕ либо по заказу, либо по плану производства. Консолидация по приведенным ниже 2м вариантам планирования приводит к уменьшению пропускной способности производства (выпуску меньшего количества заказов за период).

image

image

image


Основная (корневая)проблема и точка улучшения

Отметим еще одну, для многих — единственную, крайне важную и корневую проблему низкой эффективности производственной системы. А именно — низкая скорость реакции на внешние/внутренние возмущения.


  1. Согласно <Системной динамике> в приложении к сложным производственно-логистическим системам, все они (системы) испытывают постоянные колебания уровня запасов, и потребных/используемых мощностей, обусловленные прежде всего скоростью реакции. См.: Industrial Dynamics, Jay Forrester, Productivity Press, 1961; Factory Physics: Foundations of Manufacturing Management и производные этих работ. Частота и амплитуда колебаний прямо пропорциональны фундаментальной переменной системы — скорости реакции <на внешние и внутренние изменения>, или — времени отклика.
  2. Сокращение времени отклика (увеличение скорости реакции) увеличивает частоту колебаний запасов/мощности, но снижает их амплитуду. Амплитуда колебаний запасов (общеизвестная графическая иллюстрация колебаний — пилообразная кривая изменения уровня запасов при партионной закупке/партионной обработке) однозначно определяет объем запасов (за период), в т.ч. объем НзП в системе. При этом, согласно закону Литтла (LittleLow) <Теории очередей>, сокращение уровня запасов приводит к сокращению очередей<ПЗ в ожидании обработки>, т.е. — к сокращению циклов выполнения заказов! Подробнее: <Скорость реакции промышленного предприятия>, Питеркин С.В., интернет.
  3. Говоря <русским языком>: чаще планируем, исполняем меньшими (позаказными) партиями — больше можем выполнить заказов в единицу времени.Соотношение, которое приводилJayForrester — <сокращение времени отклика в 2 раза приводит к снижению уровня запасов по всей цепочке в 1,7 раз>. Говоря <русским языком>:
    • просто начинаем (пере) планировать всепроизводственно-логистическую цепочку чаще в 2 раза (вместо <раз в месяц> — <раз в 2 недели>) — увеличиваем выпуск <примерно>в 1,7 раз,
    • просто запускаем минимальные партии ДСЕ в производство — увеличиваем выпуск <примерно>в 1,7 раз,

    • Цифра в 1,7 — расчетная и теоретическая. Значение на практике, естественно, зависит от типа производства-закупок, типа спроса и т.п. Но как минимум, на первые десятки %% улучшения выпуска — рассчитывать можно: Просто изменяя подходы к управлению:
      Однако, глядя правде в глаза, просто изменить подходы к управлению (чаще перепланировать, чаще запускать небольшие партии), в сложном производстве, без адекватной системы планирования — невозможно.

Выводы


  1. Приведенные выше случаи — лишь небольшая часть примеров, которые наглядно показывают практическую неработоспособности представленной модели планирования. Описание всех возможных примеров и проблем при ее использовании — выходит за рамки настоящего документа. В дополнение лишь отмечу, что помимо адекватного планирования, такая система не обеспечивает и сколь-нибудь внятного мониторинга происходящего, в т.ч. позаказного мониторинга. Т.е. не дает лицам, принимающим решения, никакого инструмента по повышению продуктивности ручного управления
  2. Еще одно, крайне важное замечание! Как видно из описанныхвыше проблем, отсутствие алгоритмов <точного>, <детального>, <оптимизационного>, <планирования до станка/человека>, <планирования с учетом мощностей, , — не являются ключевыми причинами низкой эффективности большинства производственно-логистических систем. А их наличие — совсем не <золотой ключик> к ее повышению.
    Если у вас еще остались сомнения, по адекватности существующей системы планирования и/или по возможности приведения ее <в чувство> не меняя принципиальных подходов, ответьте на вопрос:<сможет ли существующая <управленческая> Система и поддерживающая ее информационная, обеспечить хотя бы недельное время отклика?>.

    Описание предлагаемых решений — в следующей части документа.

Let's block ads! (Why?)

Как написать торгового робота: инструменты для начинающих

Тема автоматизированных систем для торговли на бирже довольно популярна в рунете в последние несколько лет. Однако начинающим инвесторам создать своего торгового робота может быть нелегко. Сегодня мы расскажем о том, как это можно сделать без лишних затрат.

Примечание: любая инвестиционная деятельность на бирже связана с определенным риском, это нужно учитывать. Кроме того, для запуска своего торгового робота вам понадобится брокерский счет, открыть его можно онлайн. Вы можете отладить свою стратегию с помощью тестового доступа с виртуальными деньгами.

Варианты создания роботов


Существует несколько вариантов создания роботизированного софта для торговли на бирже:
  • Создание роботов для работы на прямом подключении – такие системы работают «в обход» торговой системы брокера, отправляя заявки напрямую в «движок» торговой системы биржи. Этот вариант используют уже опытные трейдеры, которые готовы платить в том числе и за такой способ подключения.
  • Подключение к брокерской торговой системе по API. Некоторые брокеры позволяют подключать внешний торговый софт к своим торговым системам по специальным интерфейсам. Клиенты ITI Capital могут делать это с помощью API SMARTcom. В этом случае роботы могут быть достаточно сложными.
  • Автоматизация операций напрямую в торговом терминале. Наиболее простой, подходящий для новичков способ, заключается в том, чтобы автоматизировать торговлю напрямую в базовой программе любого трейдера – терминале.

Сегодня мы будем рассматривать третий вариант, поскольку он наиболее прост.

Как это работало раньше


Торговые терминалы предыдущих поколений можно было интегрировать с различными инструментами автоматизации. Одним из наиболее популярных, как ни странно, в свое время был Excel. С его помощью трейдеры могли настроить экспорт данных из торгового терминала, а также получать торговые приказы.

Меню для подключения Excel в одном из торговых терминалов прошлого поколения

Также распространенной практикой среди трейдеров было подключение к своим терминалам мощных систем технического анализа и разработки роботов вроде WealthLab и MetaStock. В таких случаях интеграция обычно осуществляется с помощью дополнительных библиотек.

В перечисленных случаях трейдер получал возможность автоматизации, и, в случае MetaStock и WealthLab, создания довольно сложных торговых систем, но связки с внешними программами часто оказывались ненадежными. С течением времени эта проблема была решена – в некоторых торговых терминалах появились встроенные языки программирования.

Как это работает теперь: изучаем язык TradeScript


В наши дни на российском рынке самый простой способ создать несложного торгового робота, работающего с системой брокера, это использование терминала SMARTx.

В нем есть специальный плагин с конструктором торговых роботов TradeScript. С помощью простого, но довольно мощного скриптового языка трейдеры могут создавать механические системы различного уровня сложности. Язык был изначально создан для разработки торговых роботов, он довольно прост в изучении, а многие алгоритмы схожи по написанию с Metastock, что облегчает работу пользователям, знакомым с этим программным пакетом.

Плюсом TradeScript по сравнению с Wealth-Lab и тем же Metastock является отсутствие необходимости создания сложных конструкций и использования различных коннекторов для передачи приказов в торговый терминал. Конструктор роботов встроен в SMARTx, что позволяет добиваться значительно более высокой надежности и быстродействия.

Вот пример торговой стратегии, записанной на TradeScript:

Buy Signals 

# Покупаем, если момент и инерция имеют однонаправленный тренд 

TREND(EMA(CLOSE, 20), 15) = UP AND 

TREND(MACD(13, 26, 9, SIMPLE), 5) = UP 

Sell Signals 

# Продаем, если момент и инерция имеют однонаправленный тренд 

TREND(EMA(CLOSE, 20), 15) = DOWN AND 

TREND(MACD(13, 26, 9, SIMPLE), 5) = DOWN 

Exit Long Signal 

# Выходим, если тренд инерции и момента имеет противоположное направления 

TREND(EMA(CLOSE, 20), 15) = DOWN OR 

TREND(MACD(13, 26, 9, SIMPLE), 5) = DOWN 

Exit Short Signal 

# Выходим, если тренд инерции и момента имеет противоположное направления 

TREND(EMA(CLOSE, 20), 15) = UP OR 

TREND(MACD(13, 26, 9, SIMPLE), 5) = UP

В пакете с TradeScript поставляет и модуль бэктестинга, который позволяет оценить продуктивность работы описанной стратегии на исторических данных. Помимо прочего, в системе реализована функция тестирования торговой системы «на лету» с использованием текущих биржевых данных, но без вывода приказа на биржу — время виртуальной сделки, цена и получившаяся «доходность» будут показываться в отдельном окне.

Кроме того пользователь может запускать столько одновременно работающих алгоритмов, сколько позволит тактовая частота процессора и память компьютера. Учитывая большое число слов и операндов скриптового языка, это означает возможность создания сколько угодно сложных торговых стратегий.

Что еще: отладка на тестовом доступе


Использование встроенной в торговый терминал функциональности по разработке торговых роботов – удобный и надежный способ автоматизации торговли. Однако несмотря на существующие функции для тестирования стратегий, не стоит пренебрегать и дополнительными возможностями отладки.

Поэтому мы рекомендуем перед запуском стратегии для торговли реальными деньгами «прогнать» ее на тестовом доступе. Этот шаг позволит отладить все моменты, включая реакцию программы на осуществленные сделки, без риска реальных финансовых потерь. Применение анализа с помощью исторических данных, проверки «на лету» и использование тестового доступа позволит максимально полно отладить вашу стратегию.

Полезные ссылки по теме инвестиций и биржевой торговли:


Let's block ads! (Why?)