Данный проект решает задачу об инвесторе с помощью динамического программирования.
На фондовом рынке запланированы первичные размещения облигаций с номиналом 1000 условных единиц, по которым каждый день выплачивается купон размером 1 уе. Погашение номинала облигации (то есть выплата 1000 условных единиц) происходит в конце срока.
Каждая облигация на рынке характеризуется названием (некая строка) и ценой, цена выражается в виде процентов от номинала, то есть цена 98.5 соответствует цене 98,5% * 1000 = 985 условных единиц.
У некоего инвестора есть информация о том, какие предложения по облигациям будут размещаться на рынке в ближайшие N дней. По каждому дню он знает, какие лоты будут размещены на бирже: название облигации, цену и количество в штуках. Каждый день на рынке может быть от 0 до M лотов. Инвестор располагает суммой денежных средств в количестве S.
Необходимо определить какие лоты в какие дни нужно купить, чтобы получить максимальный доход с учетом следующих условий:
- Инвестор может только покупать облигации. Купленные облигации не продаются.
- Инвестор может купить только весь лот целиком при наличии доступных денежных средств.
- Выплаченные купоны по купленным облигациям не реинвестируются, то есть не Выходные данные Мегатрейдер увеличивают сумму доступных денежных средств.
- Все купленные облигации будут погашены в день N+30.
- Доход рассчитывается на день N+30, то есть после погашения облигаций.
Входные данные:
На первой строке будут даны числа N, M и S. Далее будет идти k строк вида “<день> <название облигации в виде строки без пробелов> <цена> <количество>”. Ввод будет завершен пустой строкой.
2 2 8000 1 alfa-05 100.2 2 2 alfa-05 101.5 5 2 gazprom-17 100.0 2
Выходные данные:
В первой строке необходимо указать сумму дохода, полученного трейдером на день N+30. В последующих строках привести купленные лоты в таком же формате, который используется во входных данных. Последняя строка должна быть пустой.
135 2 alfa-05 101.5 5 2 gazprom-17 100.0 2
Дополнительно необходимо указать:
- оценку необходимой памяти для его выполнения (можно экспериментально измерить)
- ограничения на размер входных параметров, при которых алгоритм будет выполняться разумное время (до 5 секунд, например)
- (если есть) использованные сторонние пакеты для оптимизированной версии (requirements.txt).
Опционально: сравнить неоптимизированную (чистый Python) и оптимизированную реализацию.
- Использование типов
NumPy
- для хранения данных используются типыnumpy.int32
иnumpy.float32
. Данный подход работает медленнее, чем встроенные типы. Это связано с тем, что динамическое программирование предполагает последовательное решение подзадач на предыдущих шагах, т.е. возникает зависимость по данным в предшествующие моменты времени, из чего следует невозможность использования быстрых векторизованных операцийnumpy
над всем скопом данных сразу. - Попытка использования
numba
не увенчалась успехом, потому что она "стремно" работает с классами, а переписывать по 10 раз один и тот же код как-то не круто. - Так как задача динамического программирования — это
рекурсивная задача, то можно написать код для ее решения
в виде рекурсии и использовать
кэширование
рекурсивных вызовов.
В итоге сравнение производиться между обычным алгоритмом (не рекурсивным) и рекурсивным с использованием кэширования.
- interfaces- директория, содержащая абстрактные классы для инвестора и облигаций.
- pure_python - содержит файлы для работы с инвестором и облигациями, используюя только встроенные типы данных python.
- with_numpy_types - аналогично
pure_python
, только с типамиnumpy
. - test_files - тестовые входные данные.
- optimization_algorithms.py - файл, который содержит описанные алгоритмы динамического программирования.
- main.py - основной файл, который обрабатывает данные.
Обязательные
параметры запуска:
-i
- путь к.txt
файлу, которые содержит входные данные.-o
- путь кдиректории
, в которую будет сохранен файл с результатами.
Не обязательные
параметры запуска:
-a
- текущий тип алгоритма:base
- не рекурсивный алгоритмbase_recursive
- рекурсивный алгоритм без кэширования (работает медленнее, чемbase
)opt
- рекурсивный алгоритм с кэшированием
-use_numpy_types
- использование типовnumpy
:0
- не использовать1
- использовать
Пример командной строки:
python main.py -a opt -i test_files\random_data_small.txt -o C:\study\script_languages -use_numpy_types 0