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

Несмотря на то, что знание последней цены полезно, я часто задаю себе вопрос: «Каковы были бы мои прибыли/убытки, если бы я продал сейчас?». Например, цена BTC может составлять 600 евро, и это может быть на 10 % больше, чем в предыдущий день, но если я купил BTC месяц назад за 660 евро, то я мог бы подумать о том, чтобы не продавать из-за 10% портфеля потери, несмотря на то, что цена валюты недавно выросла.

У Coinbase есть всеобъемлющий API, поэтому я решил создать небольшую библиотеку для решения этого вопроса. Я думаю, что важно, чтобы продукты имели такие обширные API, потому что это дает мне возможность расширять продукт для удовлетворения моих потребностей, не спрашивая ни у кого разрешения. С криптовалютами, помимо этого API уровня приложения, мы также получаем API уровня данных (то есть программируемые деньги), который позволяет использовать более сложные варианты использования настройки, чем тот, который я исследую здесь.

Я хотел поделиться парой вещей, которые я узнал/наблюдал при реализации этой библиотеки.

Бухгалтерский учет ФИФО

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

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

Пример:

Транзакции:
День 1: Купить 5 BTC за 600 €
День 2: Купить 8 BTC за 660 €
День 3: Продать 3 BTC за 700 €

Инвентарь портфеля на 4-й день:
2 BTC куплены за 600 € (раньше у нас было 5, но 3 были проданы на 3-й день)
8 BTC куплены за 660 €

Стоимость портфеля в 4-й день:
2x600€ + 8x660€ = 6480€

Неизменная структура

Чаще всего я использую immutable-struct для создания объектов-значений.
В этой библиотеке я также использовал ее, когда все еще обнаруживал соавторов объектов данного метода. Иногда вместо использования заглушки RSpec я просто создаю тип с помощью immutable-struct, а затем обновляю его до класса, когда начинаю добавлять больше поведения к этому типу.

Фактически это то, что произошло в этом коммите, я сначала создал Transaction как ImmutableStruct, чтобы я мог протестировать AssetConverter, но при реализации AssetConverter#convert я заметил, что было бы полезно, если бы Transaction имел метод price, поэтому он был обновлен до нормального класса. .

Выяснение вещей по пути

Когда я начал работать над этим, у меня было общее представление о том, что у меня будут транзакции, и объект «ликвидации», который будет реализовывать порядок учета FIFO и рассчитывать прибыли/убытки.

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

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

Именование

Именование всегда сложно. Большая часть используемых терминов пришла из чтения документации API, чтения о нескольких методах учета и чтения о нескольких способах расчета доходности портфеля акций — так что знакомство с предметной областью. Словарь и его раздел тезауруса также всегда пригодятся.
Хотя мне очень нравится правильно формулировать термины, на начальном этапе моей главной целью является создание правильных тестов и поведения, потому что после того, как у меня будут хорошие тесты, изменить имена будет легко. Также легче заметить несоответствия после того, как я получу четкую общую картину.
Вероятно, поэтому у меня есть пара коммитов, переименовывающих кучу вещей в конце. Если история коммитов окажется запутанной, ее всегда можно переписать.

Частный attr_reader

У меня есть привычка использовать private attr_reader, поэтому я могу получить доступ к переменным экземпляра, используя метод вместо префикса @ (т.е. @transaction против transaction). Я, вероятно, обнаружил это в книге или скринкасте (но не могу вспомнить, в каком именно).
Я, вероятно, предпочитаю рассматривать все как методы из-за подсветки синтаксиса или меньшего количества символов для ввода, но у меня нет четкого мнения по этому вопросу.

Заключительные мысли

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

Первоначально опубликовано на сайте blog.marionzualo.com 30 октября 2016 г.