Русский
Русский
English
Статистика
Реклама

Scraping

Перевод Визуализация списка женщин-лауреатов Нобелевской премии в виде кристаллов в 3d с использованием Vue, WebGL, three.js

13.06.2020 22:23:27 | Автор: admin
image

Год 1 | вдохновение


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

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


1 неделя | данные


После формирования концепции, возник следующий вопрос как собрать необходимые данные? Я быстро пришла к идее использовать Википедию, попытаться спарсить лучших женщин оттуда. Я понятия не имела, как определить лучших (просмотры страницы? длина страницы? ссылки на страницу?). Хотя я посмотрела статью на The Pudding про визуализацию на основе данных википедии, я все еще не была уверена, что хочу двигаться в эту сторону. А еще мне очень не хватало свободного времени.

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

image

С этого момента я начала изучать разные методы использования API Википедии. Разобраться было непросто (я не была уверена, нужно ли мне использовать Wikidata или MediaWiki, это те варианты, которые возникали при поиске Wikipedia API в Google), но, к счастью, уже упомянутая выше статья на Pudding помогла мне закрыть эти вопросы. Быстрый просмотр их репозитория wiki-billboard-data привел меня к выбору одного из скриптов с wikijs, и я могла просто воспользоваться этим пакетом.

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

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


Затем я экспортировала электронную таблицу как CSV, потом использовала онлайн-конвертер, чтобы получить данные в формате JSON.

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

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

неделя 2 | скетч


Не буду врать, я так долго думала об этом проекте, что даже не могу вспомнить все идеи, которые у меня возникали в процессе. Все, что я помню, это то, что я просматривала номинантов премии Information is Beautiful, когда решила, что мне нужно как-то выделить те записи, которые мне действительно нравятся в моих сохранениях. Это заставило меня осознать, что я должна лучше организовать свою доску на Pinterest, так как раньше я сваливала все мои идеи и видение на одну доску. В процессе чистки, я наткнулась на эту великолепную картину с кристаллами художника Ребекки Шаперон, которую я сохранила на будущее несколько лет назад. Почти сразу я поняла, что я хочу программно воссоздать их. Ведь было бы прекрасно визуализировать этих выдающихся женщин в качестве ярких разноцветных кристаллов?

image

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

После этого я продумала другие детали: размер кристаллов должен отражать влияние женщины количество ссылок на ее страницу в Википедии. Число граней на кристалле будет сопоставлено с количеством источников в нижней части ее страницы (поскольку она многогранна), а цвет будет определяться категорией премии. Единственное, что мне пока было непонятно, это как расположить кристаллы. Я долго думала, что мне надо просто выложить их в 2-х измерениях по x / y и заставить читателя прокручивать их.

А потом я приняла участие в семинаре Мэтта ДесЛориерса по креативному кодингу, где он преподавал canvas, three.js и WebGL. Семинар открыл мне концепт третьего измерения, и я сразу поняла, что собираюсь использовать год получения награды в качестве оси z. Далее один мой друг предложил сделать потоки-нити, связывающие тех, кто сотрудничал друг с другом таким образом, чтобы их положение тоже менялось в зависимости от этого (но в итоге у меня не было времени на реализацию этой идеи).

Вся концепция пришла ко мне так быстро и естественно, что я не сделала ни одного наброска в процессе. Я просмотрела свой блокнот, но там вообще ничего нет.

неделя 3 & 4 | кодинг


Это был отличный месяц для кодинга.

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

И вот однажды меня осенило (я не уверена, что послужило причиной), что я не умею думать в трехмерном физическом пространстве, как раз потому, что я постоянно работаю в плоском диджитальном формате. Если бы я смогла научиться работать с 3D в цифре, то смогла бы мыслить в объеме и в физическом мире. Я добавила three.js и WebGL вверх своего списка для изучения.

В конце октября я прошла семинар Мэтта по креативному кодингу и изучила основы three.js, введение в фрагментированные и вершинные шейдеры. Я выучила правило буравчика: используйте большой палец для оси X (увеличивается вправо), указательный палец для оси Y (увеличивается вверх, что противоположно SVG и canvas) и средний палец для оси Z (для увеличения экрана и приближения его). Я узнала, что WebGL работает не в пикселях, а в единицах (похожая ассоциация футы или метры).

Затем в ноябре я вписалась в один конкурс по WebGL. Хотя я раньше не имела с ним дела, я надеялась, что дедлайн даст мне мотивацию, необходимую для завершения проекта. Я начала 1-го декабря и поставила себе цель делать чуть-чуть каждый будний день, пока не смогу дойти до чего-то презентабельного 23-го декабря (финал конкурса).

Сперва я прочла первые две главы Руководства по программированию на WebGL, в котором рассказывалось, как настроить WebGL. Затем я повторила свои знания по three.js. После я запустила блокнот из Observable, чтобы понять минимально-необходимые настройки для рисования чего-либо в three.js (рендерер, камера и сцена, а затем вызвать renderer.render(scene, camera) для отображения ). Мне всегда нравилось понимать самые основы работы кода, так что это было очень полезно.

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

image

А во второй день кристалл (на который потребовалось две попытки, потому что в первый раз я налажала с математикой).

image

А потом, в конце концов, форма кристалла, который был у меня в голове.

image

Позже я поняла, что есть лучшие способы делать то, что я хотела (и на самом деле PolyhedronGeometry это довольно утомительный способ делать это), но я была очень рада возможности попрактиковаться в координатах x / y / z в WebGL.

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

image

Следующей задачей стало научиться использовать фрагментный шейдер для окрашивания кристалла. Здесь мне пришлось немного отклониться от плана, потому что я не могла понять, как использовать glslify (узловая модульная система для GLSL, на которой написаны шейдеры, которые я взяла в качестве образца). Вместо этого я начала изучать различные инструменты компоновки/сборки, чтобы в конечном итоге развернуть свой код в Интернете. В конце концов, я решила использовать Parcel (вместо Vue CLI, который я регулярно использую последние полгода), потому что он имеет встроенную поддержку как Vue, так и GLSL.

Вот такой кристалл с наложением того же паттерна шума у меня получился.

image

Результат мне не нравился, поэтому я решила, что мне нужно больше узнать о шейдерах и использовании цветов в шейдерах. Именно в этот момент я обратилась к Books of Shaders Патрисио Гонсалеса Виво и, в частности, к главе Shaping Functions. Я узнала о синусах, косинусах, полиномах и экспонентах функциях, которые могут брать число (или набор чисел) и выводить на их основе другие. Я также узнала о смешивании цветов и о том, как мы можем взять два цвета, и не только получить новый цвет посередине между этими двумя, но также смешивать цвета в формате RGB и создавать совершенно новые на их основе. Если мы объединим это с функциями формы, то сможем получить градиенты и формы:

image
Эти были получены путем смешивания синего и желтого, а также изменения значений RGB в каждой позиции с помощью степеней, синусов, абсолютных значений, шагов и сглаживаний

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

image

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


Примерно в это же время я наткнулась на демо Bloom (эффект постобработки для создания свечения), и в нем были круглые, похожие на драгоценные камни объекты, которые выглядели довольно похоже на кристаллы, которые я и хотела получить:

image

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

Поэтому я заменила PolyhedronGeometry на SphereGeometry, установила высоту на 4 и ширину на свои данные, растянула фигуру, установив вертикальный масштаб в два раза больше по горизонтали, добавила jitter (дрожание) для каждой вершины, и у меня получились гораздо более интересные формы:

image

Теперь, когда я определилась с формами, настало время вернуться к цвету. На этот раз я использовала два цвета и смешивала их с функциями формы:

image
image
Мне нравится первый вариант выглядит как картофель

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

image
Код для добавления нормалей сторон.

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

image

Затем занялась фоном. Я создала пол с помощью PlaneGeometry и случайного дрожания y-позиции каждой вершины (вдохновленной этой статьей из codrops), а также небо, создав огромную сферу вокруг сцены. Я экспериментировала с тремя различными типами источников света: полусферой, рассеянным (чтобы создать длянеба ощущение заката/восхода солнца), и направленным (чтобы отбрасывать тени от кристаллов на пол).

image

В конце я добавила звездочки, которые визуализируют всех мужчин, которые выиграли премию за тот же период времени, а также аннотации для каждого кристалла и для десятилетий. Это было сложно, потому что с тем текстом, который у меня был, использовать TextGeometry было практически бесполезно. Решение, которое я нашла после поиска в интернете, визуализировать текст в HTML5 Canvas, создать PlaneGeometry и использовать этот Canvas в качестве текстуры для заполнения PlaneGeometry. Очень интересный подход.

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

image

Вот ссылка на финальный результат на GitHub

И видео c демонстрацией результата:



Если вы хотите попробовать еще что-то или начать с более простых проектов:

Подробнее..

Сбор данных и отправка в Apache Kafka

15.11.2020 20:17:49 | Автор: admin

Введение


Для анализа потоковых данных необходимы источники этих данных. Так же важна сама информация, которая предоставляется источниками. А источники с текстовой информацией, к примеру, еще и редки.
Из интересных источников можно выделить следующие: twitter, vk. Но эти источники подходят не под все задачи.
Есть источники с нужными данными, но эти источники не потоковые. Здесь можно привести следующее ссылки: public-apis.
При решении задач, связанных с потоковыми данными, можно воспользоваться старым способом.
Скачать данные и отправить в поток.
Для примера можно воспользоваться следующим источником: imdb.
Следует отметить, что imdb предоставляет данные самостоятельно. См. IMDb Datasets. Но можно принять, что данные собранные напрямую содержат более актуальную информацию.


Язык: Java 1.8.
Библиотеки: kafka 2.6.0, jsoup 1.13.1.


Сбор данных


Сбор данных представляет из себя сервис, который по входным данным загружает html-страницы, ищет нужную информацию и преобразует в набор объектов.
Итак источник данных: imdb. Информация будет собираться о фильмах и будет использован следующий запрос: https://www.imdb.com/search/title/?release_date=%s,%s&countries=%s
Где 1, 2 параметр это даты. 3 параметр страны.
Для лучшего понимания источника данных можно обратится к следующему ресурсу: imdb-extensive-dataset.


Интерфейс для сервиса:


public interface MovieDirectScrapingService {    Collection<Movie> scrap();}

Класс Movie это класс, которые содержит информацию об одном фильме (или о шоу и т.п.).


class Movie {    public final String titleId;    public final String titleUrl;    public final String title;    public final String description;    public final Double rating;    public final String genres;    public final String runtime;    public final String baseUrl;    public final String baseNameUrl;    public final String baseTitleUrl;    public final String participantIds;    public final String participantNames;    public final String directorIds;    public final String directorNames;

Анализ данных на одной странице.
Информация собирается следующим образом. Данные закачиваются с помощью jsoup. Далее ищутся нужные html-элементы и трансформируются в экземпляры для фильмов.


String scrap(String url, List<Movie> items) {    Document doc = null;    try {        doc = Jsoup.connect(url).header("Accept-Language", language).get();    } catch (IOException e) {        e.printStackTrace();    }    if (doc != null) {        collectItems(doc, items);        return nextUrl(doc);    }    return "";}

Поиск ссылки на следующею страницу.


String nextUrl(Document doc) {    Elements nextPageElements = doc.select(".next-page");    if (nextPageElements.size() > 0) {        Element hrefElement = nextPageElements.get(0);        return baseUrl + hrefElement.attributes().get("href");    }    return "";}

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


@Overridepublic Collection<Movie> scrap() {    String url = String.format(            baseUrl + "/search/title/?release_date=%s,%s&countries=%s",            startDate, endDate, countries    );    List<Movie> items = new ArrayList<>();    String nextUrl = url;    while (true) {        nextUrl = scrap(nextUrl, items);        if ("".equals(nextUrl)) {            break;        }        try {            Thread.sleep(50);        } catch (InterruptedException e) {        }    }    return items;}

Подробности по остальным методам можно найти в ссылках на ресурсы.


Отправка данных в топик


Формируется следующий сервис: MovieProducer. Здесь будет один единственный публичный метод: run.


Создается продюсер для кафки. Загружаются данные из источника. Трансформируются и отправляются в топик.


public void run() {    try (SimpleStringStringProducer producer = new SimpleStringStringProducer(            bootstrapServers, clientId, topic)) {        Collection<Data.Movie> movies = movieDirectScrapingService.scrap();        List<SimpleStringStringProducer.KeyValueStringString> kvList = new ArrayList<>();        for (Data.Movie move : movies) {            Map<String, String> map = new HashMap<>();            map.put("title_id", move.titleId);            map.put("title_url", move.titleUrl);                        String value = JSONObject.toJSONString(map);            String key = UUID.randomUUID().toString();            kvList.add(new SimpleStringStringProducer.KeyValueStringString(key, value));        }        producer.produce(kvList);    }}

Теперь все вместе


Формируются нужные параметры для поиска. Загружаются данные и отправляются в топик.
Для этого понадобится еще один класс: MovieDirectScrapingExecutor. С одним публичным методом: run.


В цикле создаются данные для поиска из текущей даты. Происходит загрузка и отправка данных в топик.


public void run() {    int countriesCounter = 0;    List<String> countriesSource = Arrays.asList("us");    while (true) {        try {            LocalDate localDate = LocalDate.now();            int year = localDate.getYear();            int month = localDate.getMonthValue();            int day = localDate.getDayOfMonth();            String monthString = month < 9 ? "0" + month : Integer.toString(month);            String dayString = day < 9 ? "0" + day : Integer.toString(day);            String startDate = year + "-" + monthString + "-" + dayString;            String endDate = startDate;            String language = "en";            String countries = countriesSource.get(countriesCounter);            execute(language, startDate, endDate, countries);            Thread.sleep(1000);            countriesCounter += 1;            if (countriesCounter >= countriesSource.size()) {                countriesCounter = 0;            }        } catch (InterruptedException e) {        }    }}

Для запуска потребуется экземпляр класса MovieDirectScrapingExecutor, который можно запустить с нужными параметрами, к примеру, из метода main.


Пример отправляемых данных для одного фильма.


{  "base_name_url": "https:\/\/www.imdb.com\/name",  "participant_ids": "nm7947173~nm2373827~nm0005288~nm0942193~",  "title_id": "tt13121702",  "rating": "0.0",  "base_url": "https:\/\/www.imdb.com",  "description": "It's Christmas time and Jackie (Carly Hughes), an up-and-coming journalist, finds that her life is at a crossroads until she finds an unexpected opportunity - to run a small-town newspaper ... See full summary ",  "runtime": "",  "title": "The Christmas Edition",  "director_ids": "nm0838289~",  "title_url": "\/title\/tt13121702\/?ref_=adv_li_tt",  "director_names": "Peter Sullivan~",  "genres": "Drama, Romance",  "base_title_url": "https:\/\/www.imdb.com\/title",  "participant_names": "Carly Hughes~Rob Mayes~Marie Osmond~Aloma Wright~"}

Подробности можно найти в ссылках на ресурсы.


Тесты


Для тестирования основной логики, которая связана с отправкой данных, можно воспользоваться юнит-тестами. В тестах предварительно создается kafka-сервер.
См. Apache Kafka и тестирование с Kafka Server.


Сам тест: MovieProducerTest.


public class MovieProducerTest {    @Test    void simple() throws InterruptedException {        String brokerHost = "127.0.0.1";        int brokerPort = 29092;        String zooKeeperHost = "127.0.0.1";        int zooKeeperPort = 22183;        String bootstrapServers = brokerHost + ":" + brokerPort;        String topic = "q-data";        String clientId = "simple";        try (KafkaServerService kafkaServerService = new KafkaServerService(                brokerHost, brokerPort, zooKeeperHost, zooKeeperPort        )        ) {            kafkaServerService.start();            kafkaServerService.createTopic(topic);            MovieDirectScrapingService movieDirectScrapingServiceImpl = () -> Collections.singleton(                    new Data.Movie()            );            MovieProducer movieProducer =                    new MovieProducer(bootstrapServers, clientId, topic, movieDirectScrapingServiceImpl);            movieProducer.run();            kafkaServerService.poll(topic, "simple", 1, 5, (records) -> {                assertTrue(records.count() > 0);                ConsumerRecord<String, String> record = records.iterator().next();                JSONParser jsonParser = new JSONParser();                JSONObject jsonObject = null;                try {                    jsonObject = (JSONObject) jsonParser.parse(record.value());                } catch (ParseException e) {                    e.printStackTrace();                }                assertNotNull(jsonObject);                    });            Thread.sleep(5000);        }    }}

Заключение


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


Ссылки и ресурсы


Исходный код.

Подробнее..

Скрапинг avito без headless-браузера

18.01.2021 22:06:54 | Автор: admin

Недавно на хабре вышла статья Скрапинг современных веб-сайтов без headless-браузеров, и в комментариях было высказано мнение, что без headless-браузера не выйдет получить номер телефона из объявления на "авито" или "юле". Хочу это опровергнуть, ниже скрипт на python размером менее 100 строк кода, который успешно парсит "авито"

Я не являюсь специалистом по "парсингу" сайтов и это не моя работа, но не редки случаи, когда для решения моих рабочих, и не только задач, приходится это делать. Например необходимо получить баланс лицевого счета в каком-то сервисе(мобильные операторы), который не имеет для этого API или, что совсем печально, список доменов у регистратора (ещё один), который так-же не имеет API.

Как и в статье, пара комментариев из которой побудили меня написать этот пост, я тоже использую Python и библиотеку requests. Если не удается найти "внутренний" API , то приходится подключать библиотеку BeautifulSoup. Но тут всё оказалось намного проще.

Если открыть "полную" версию сайта https://avito.ru, и попытаться скопировать номер телефона, то станет понятно, что номер телефона на сайте не написан, а нарисован. Но в мобильной версии сайта, номер отдается текстом. Это можно проверить, если в инструментах разработчика в браузере посмотреть ответы при нажатии на кнопку "Позвонить".

Я не буду детально разбирать свой скрипт, в коде достаточно комментариев, чтоб понять что и на каком этапе происходит. Если кратко, то используется мобильная версия сайта, объявляются переменные для поиска по сайту а так-же две переменные "key" и "cookie", о них далее подробнее, потом идет процесс получения куки путем открытия главной страницы, далее запускается цикл, которые собирает id всех объявлений проходя по всем страницам. После того, как получены все объявления вторым циклом проходим по ним и получаем интересующую нас информацию.

Скриншот работы скрипта:

Всё так легко выглядит, т.к. были найдены нужные API. По сути данный скрипт похож на такой-же будь в нем применены официальные API. Я старался не добавлять функции и не проверять ответы на корректность или обрабатывать исключения, это ведь демонстрация метода, а не боевой инструмент. На мой взгляд так понятнее. Хотя несколько проверок и обработок там всё-же есть. Так-же я старался уместить скрипт в 100 строк кода.

По поводу переменных "key" и "cookie", key как я понял статичен, он легко гуглится, то-есть не генерируется на ходу. cookie же я использовал, как простой "антиблок", как оказалось вердикт, что мой IP заблокирован на самом деле не является правдой, достаточно подсунуть свежие куки и "парсинг" продолжается.

Если будет интересно, я подробнее расскажу, как я искал API или могу подобный пример написать и для "юла".

Сам скрипт

Подробнее..
Категории: Scraping , Python , Api , Web , Python3 , Requests

Инвестирование в отраслевые фонды в Экселе

03.02.2021 12:13:25 | Автор: admin

Написать эту статейку меня побудила замечательная серия многоуважаемого @abak "Теория инвестиций для начинающих". В качестве конфетки внизу даю ссылку на табличку, получающую текущие цены на европейские фонды, их прибыльность и другие параметры из интернета. Кроме того мне хотелось бы немного расширить изначальную статью с точки зрения начинающего инвестора, инвестирующего из дома и лишенного вкусностей внутренней кухни Дойче банка.

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


Почему фонды

Хотя вся необходимая информация и доступна и бесплатна, докопаться до реально работающих схем, приносящих доход, каждому приходится самому. Та пена, которую все ежедневно видят на баннерах типа: Покупай акции такие-то и продавай такие-то не имеют ничего общего с реальной жизнью. В частности, реклама фондов, рассылаемая банками (Вложись в супер-ETF и обрети целых 4.5% годовых!!!), оказала на автора противоположное действие и отложило инвестиции в фонды на три года. Прежде чем перейти к фондам я остановлюсь на минусах акций и облигаций.

Акции:

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

  • Анализ всяких технических вкусностей вроде ROE (см. finance.yahoo.com, раздел Statistics и Financials), а также прибылей за определённые промежутки времени, по аналогии с выложенной таблицей для оценки фондов, даёт прибыльность меньшую, нежели фонды.

  • Высокая волатильность.

  • Абсолютно непонятна логика/психология рынка: Почему если в новостях говорят о том, что у фирмы был хороший или плохой год, курс может как упасть, так и подняться. Где логика?

  • С акциями такое чувство, будто все фирмы мухлюют с отчётностью (привет, Wirecard!)

Облигации:

  • Низкая доходность

  • Можно по недосмотру нарваться на что-то экзотическое, например на облигацию, которая погашается по мере приближения к моменту погашения, зато

Куча плюсов облигаций:

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

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

  • В случае дефолта, владельцы облигаций обладают преимуществом при получении имущества обанкротившейся фирмы (проданного конечно, никто не пришлёт Вам по почте старый стул). Правда выплат по дефолтным облигациям можно ждать лет десять: года три назад я с удивлением увидел в поиске облигаций Lehman Brothers.

Поэтому я выбрал

Фонды

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

Чтобы облегчить себе, а теперь уже и вам, жизнь, я составил табличку на старом добром Экселе, которая грабит данные с сайта ariva.de. Так как странички иногда меняют формат и наполнение, то табличка требует постоянного ухода, что я постараюсь и делать через GitHub. В общем, снимаю шляпу перед теми, кто занимается скрэпингом профессионально: это редкостное болото, вытянуть из которого что-то дельное очень не просто.

Таблица

Для тех, кто никогда не работал с Selenium в Экселе, существует библиотека SeleniumBasic. Коротенькое описание установки для работы с ней приведено здесь. По нажатии на Update, таблица загружает данные о прибыли ценной бумаги (ЦБ) с сайта ariva.de.

Внутренности таблицы:

Таблица настроена на работу с запятой в качестве разделителя между целой и дробной частями числа. Американский формат записи, через точку, не тестировался.

Табличка подробнее
  • WKN (Колонка C): Немецкий аналог Международного идентификационного кода ценной бумаги (ISIN), только короче. ISIN настолько международный, что finance.yahoo.com им не пользуется, предпочитая свои, мериканьские, обозначения. Дикари-с. WKN-единственный обязательный входной параметр таблицы.

  • Favorites (Колонка D): Если ячейка пуста, и чек-бокс Update only favorites отмечен, то для ускорения данная ЦБ будет пропущена. Раз в неделю я обновляю данные по всем ЦБ, но чаще всего только по тем, которые меня интересуют.

  • Страна (Колонка E): Страна не всегда обновляется корректно. В таких случаях ячейка со страной остаётся пустой.

  • Отрасль (Колонка F): Довольно грубое деление по отраслям. На немецком, так что гугл транслейт в помощь. Используется чтобы равномерно распределить ЦБ по разным секторам экономики.

  • Benchmark (Колонка G): Из какого индекса набраны акции.

  • Валюта (Колонка H): Тут всё понятно. Сайт видимо переводит всё в евро, а потому иные валюты я пока не встречал.

  • URL (Колонка I): В случае отсутствия автоматически обновляется по WKN.

  • Прибыль ЦБ за определённый период (Колонки J - N): Прибыль за 3/6 месяцев, 1/3/5 лет. Зелёным цветом помечены ЦБ из верхнего 85% перцентиля, красным из нижнего 15% перцентиля.

  • Время обновления (Колонка O): Если ЦБ уже была обновлена сегодня, то при повторном обновлении (тоже сегодня) она будет пропущена.

  • Остальные колонки говорят сами за себя: Цена в евро (Колонка P), Альфа (Колонка Q), Бета (Колонка R): Отношение Шарпа (Колонка S).

  • Сортировка осуществляется автоматически, выбором соответствующего критерия лист-боксом. Для сортировки важны данные после ключевого слова Sorting в колонке A. Категории перечислены в ячейках A59:A67, после которых (колонка B) идут формулы выбора соответствующей колонки для сортировки и вид сортировки, по возрастанию (TRUE) или убыванию (FALSE).

Цель таблицы: Обновить данные и предоставить мне и вам удобные сортировки по разным критериям:

  • 3m/6m/1yr/3yrs/5yrs: Доходность ЦБ за данный период в процентах. В принципе меня обычно интересует только доходность за последние 3 месяца.

  • Положение (место) в каждой категории (3m/6m) вычисляется в колонках AB:AI.

  • Ну и в колонке AJ находится сумма всех категорий. Теоретически, чем меньше число, тем больший доход принесёт фонд. Стоит также отменить, что в сумму входят так же значения альфа и бета и отношение Шарпа, хотя они не являются линейнозависимыми. В общем можно и альфа и бета выкинуть.

В качестве простеньких бонусов:

Часто задают вопрос: А откуда следует, что если фонд давал прибыль в прошлом, то он будет давать прибыль и в будущем? Для ответа нарисуем график прибыли между 6 месяцами и 3 месяцами (условное будущее) и между годом и 6 месяцами (прошлое). Как видно из графика, чем больше прибыль в прошлом, тем больше прибыль и в будущем. Если убрать сильно выпадающие точки в верхней части графика, то коэффициент корреляции будет ещё выше: 0.2. Для автора этот результат был откровением, так как автор ожидал более хаотичного распределения точек. И, не забываем, что посредине, между 6 месяцами и годом был кризис в виде ковида. Выпадающие две верхних точки относятся к зелёной энергетике, т. Е. к хайпу в настоящий момент. Конечно, хотелось бы, чтобы наклон был больше, но ведь растёт!

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

Как работает табличка

Сперва несколько простых напоминаний, которые все знают, но без которых никуда:

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

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

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

Что я стараюсь делать:

  • Продаю ЦБ только не ранее 3 месяцев после покупки. Даю каждой ЦБ шанс показать на что она способна. А могу и продать и раньше хозяин счёта всё-таки я, а не табличка.

  • Если ЦБ лежит на счету уже более 3 месяцев и выбывает из первой десятки, то могу её продать и купить что-то из первой пятёрки.

  • Когда наступает время очередного зуда и хочется продать или купить или и то и другое, я залезаю на finanzen.net/ariva.de в раздел Fonds/ETFs в разделы Fonds-Suche и ETF-Suche (поиск по фондам и ETF), ищу фонды с максимальной прибыльностью за год и вношу их в табличку. Таким образом проблема попасть на фонд вроде индексного фонда японского рынка и зависнуть на десятилетия в минусах практически невозможна.

Что я стараюсь не делать:

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

  • Вкладываться в хайп: Руки, конечно, чешутся, но Тесла/Биткоин не для меня. Если хотите, чтобы Тесла/Биткоин обрушилась, напишите мне и я их куплю. Убытки поделим пополам :-)

  • Меня смущают фонды, не торгующиеся на бирже (пример: green benefit Global Impact Fund). Да, он есть в моей копилке, но его покупка растянулась на три дня, так что быстро избавиться от него в течение 10 минут и по нужной цене скорее всего не удастся.

  • Не связываюсь с акциями и облигациями европейских фирм: К ним у меня никакого доверия после банкротства AirBerlin и Sympatex, чьи дефолтные облигации до сих пор висят мёртвым грузом на моём счету. Только моя медлительность спасла меня от покупки Wirecard прямо перед их дефолтом. Да и Баффета недавно немцы обидели.

  • Я не вкладываю в ЦБ дополнительных денег и вот почему (это лишь моё видение, оно не критично, у каждого свой стиль инвестирования):

  • Фонд должен приносить деньги мне, а не я ему. Поэтому 10% прибыли я вывожу и вкладываю в покупку золота, наличной валюты (можно и в тушенку/патроны, зависит от фантазии), в НЗ, на случай если всё обрушится.

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

А это ни тепло, ни холодно:

  • Комиссия инвестиционной компании (ИК): Не особо обращаю внимания на комиссию. В некоторых случаях она достигает 5%, но и отдача фонда в таком случае может быть неплохой.

  • StopLoss-ы: Иногда применяю, но чаще нет. Их иногда внезапно срывает, после чего позиция откатывается на старые значения. Но уже без меня.

  • Продавать всё во время кризиса. Да, в этот раз (март 2020) стоп-лоссы сработали как часы и я всё быстро распродал, в основном с прибылью. Но потом рынки достаточно быстро восстановились и я еле успел вложиться. Так что вышло то на то.

  • Можно застраховать фонды через Put-опционы. Тут у меня двойственная позиция:

  • Покупать: Автор предпочитает спать спокойно и видеть, что счёт в ИК не зависит от падения рынка.

  • Не покупать: Автор предпочитает спать спокойно, а не подгадывать момент, когда рынок упал с целью продать опцион.

  • В общем, и так и эдак плохо. Реально, последние две мои покупки опционов закончились потерей денег, ну а в сумме: плюс/минус ноль.

Количество фондов: Не имеет значения, главное в верхней трети таблицы. Сейчас 7. Инвестирую каждый раз приблизительно одну и ту же сумму денег, чтобы потом легче было посмотреть где и сколько выиграл/проиграл.

Инвестиционный диапазон: В моём случае, редко какой фонд задерживается более чем на год, но я инвестор скорее нервный, чем рисковый.

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

Риски

  • Доллар обрушится, обрушится: Честно говоря, не верю по одной причине:

  • Штаты собирают налоги со всего мира: Вот с какого бодуна мне приходится регулярно заполнять форму W-8BEN и посылать её в ИК, хотя я ни разу не гражданин США, а лишь купил их акции или АДР (американские депозитарные расписки)?

  • А вдруг будет новый кризис?

  • Кризис будет, но, экономика сейчас достаточно устойчива. Проверено корона-вирусом.

  • А вдруг завтра война?

  • Очень возможно, учитывая события 2014 года. В этом случае все накопления превратятся в ничто и именно на этот случай 10% прибыли и откладываются в НЗ (золото/тушенка/патроны). Автор до сих пор с содроганием вспоминает прочитанные в школе рассказы очевидцев о блокадном Ленинграде, когда за золото выменивали килограмм требухи типа лёгких.

  • А как на счёт искусственного раскачивания лодки, вроде того что сделали с GameStop?

  • Вот это действительно рискованно. Надеюсь у них хватит такта остановиться. А вообще, вся ситуация с GameStop сильно напоминает Россию в февральскую революцию, когда кучке большевиков удалось расшатать за пару месяцев огромную империю. Есть в Reddite что-то анархо-большевицкое.

Заключение

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

Ссылка на табличку

Будьте здоровы!

Живите богато!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru