{"id":20392327,"url":"https://github.com/wiseplat/hackathon-moex-how-to-guide","last_synced_at":"2025-09-24T01:31:05.661Z","repository":{"id":211869484,"uuid":"730142360","full_name":"WISEPLAT/Hackathon-MOEX-How-To-Guide","owner":"WISEPLAT","description":"🏅Номинация «How to guide» - Как сделать торгового робота за 15 минут с нуля","archived":false,"fork":false,"pushed_at":"2023-12-11T09:56:26.000Z","size":12,"stargazers_count":3,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-06T05:23:45.666Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WISEPLAT.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-12-11T09:48:06.000Z","updated_at":"2024-12-23T17:09:34.000Z","dependencies_parsed_at":"2023-12-11T10:49:18.380Z","dependency_job_id":"58c1dea2-bfd8-475f-9256-b30d97ba21c9","html_url":"https://github.com/WISEPLAT/Hackathon-MOEX-How-To-Guide","commit_stats":null,"previous_names":["wiseplat/hackathon-moex-how-to-guide"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/WISEPLAT/Hackathon-MOEX-How-To-Guide","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WISEPLAT%2FHackathon-MOEX-How-To-Guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WISEPLAT%2FHackathon-MOEX-How-To-Guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WISEPLAT%2FHackathon-MOEX-How-To-Guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WISEPLAT%2FHackathon-MOEX-How-To-Guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WISEPLAT","download_url":"https://codeload.github.com/WISEPLAT/Hackathon-MOEX-How-To-Guide/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WISEPLAT%2FHackathon-MOEX-How-To-Guide/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":276678844,"owners_count":25684803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-23T02:00:09.130Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-15T03:43:23.188Z","updated_at":"2025-09-24T01:31:05.409Z","avatar_url":"https://github.com/WISEPLAT.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🏅Номинация «How to guide» - Как сделать торгового робота за 15 минут с нуля\n## Пошаговое руководство Hackathon-MOEX-How-To-Guide\n\n```\nПеред прочтением этой статьи — ВАЖНО следующее: основная цель данной статьи заключается в том, чтобы показать \nкак просто можно создать торгового робота, который может торговать российскими акциями или зарубежными акциями. \nВажно понимать, что создавая бота, вы лично несете ответственность за принимаемые им решения, инвестиционные \nоперации и связанные с ними риски. Я не несу ответственности за решения, которые вы можете принять после \nпрочтения этого материала. И я не даю никаких инвестиционных рекомендаций или советов. \nНе забывайте, что боты способны принести большие убытки, поэтому используйте их с осторожностью.\n\nПошаговое руководство по созданию торгового робота в рамках соревнования Хакатон [GO ALGO] организатором которого выступает биржа MOEX.\n```\n\n## Выбор брокера и библиотек\nКак вы знаете, брокеров много))) но нам нужны те, у которых есть API — программный интерфейс через который наш торговый робот сможет отправлять заявки на покупку и продажу акций.\n\nВ этой статье будем рассматривать Российских брокеров для торговли Российскими акциями, если вы захотите торговать иностранными акциями — то это тоже можно сделать через них же — через СПБ биржу. (код торгового робота не поменяется — поменяется только название тикера — торговой бумаги, которой вы будете торговать).\n\nЧтобы вас долго не мучать с выбором хорошего брокера для торгового бота, я приведу мои решения, которые сформировались после длительной практики по написанию торговых ботов, работающих в live режиме — прямо сейчас торгующих российскими акциями.\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list01.jpg)\nсписок сделок за сегодня, таймфрейм H1\n\nНужный и важный компонент в разработке торгового бота — это возможность тестирования вашей стратегии на истории, например используя простую библиотеку [Backtrader](https://github.com/WISEPLAT/backtrader ).\n\nИтак приступим! )))\n\n**1й вариант** — если очень сильно хочется иметь робота, который может торговать практически через любого брокера — то есть очень хорошее решение использовать библиотеку [QuikPy](https://github.com/cia76/QuikPy ) в связке с библиотекой [BackTraderQuik](https://github.com/cia76/BackTraderQuik ) — использование этих двух библиотек позволит вашему торговому роботу работать с любым брокером, у которого есть возможность предоставить вам торговый терминал **Quik**. А этот торговый терминал есть у большинства брокеров.\n\nМножество примеров по этой связке специально для вас выложил [вот здесь](https://github.com/WISEPLAT/Learn-BackTrader ).\n\n**2й вариант** — он немного ограничивает в выборе брокеров, но даёт прекрасную возможность общаться с разработчиками API брокеров, и они!!! заметьте быстро и эффективно исправляют косяки) и добавляют функционал — это большой плюс!\n\nДля брокера Финам — библиотеки [FinamPy](https://github.com/cia76/FinamPy ) + [BackTraderFinam](https://github.com/cia76/BackTraderFinam )\n\nДля брокера Тинькофф — библиотеки [TinkoffPy](https://github.com/cia76/TinkoffPy ) + [BackTraderTinkoff](https://github.com/cia76/BackTraderTinkoff )\n* Несколько примеров кода опубликовал в их репозитории — [пример стратегии](https://github.com/Tinkoff/invest-python/blob/main/examples/wiseplat_live_strategy_print_ohlcv.py ) которая использует только API Тинькофф\n\nДля брокера Алор — библиотеки [AlorPy](https://github.com/cia76/AlorPy ) и [BackTraderAlor](https://github.com/cia76/BackTraderAlor )\n\nОФФТОПИК: Если кому интересно подключение к криптобирже — то я написал свою библиотеку [backtrader_binance](https://github.com/WISEPLAT/backtrader_binance ), она работает так же, т. е. один и тот же код, можно использовать для разных активов, вот про [нее статья](https://habr.com/ru/articles/729036/ ).\n\nИтак, выбираем последнего брокера — Алор. ))\n\n## Приступаем к написанию торгового бота\n\n\nУстанавливаем последнюю версию [Python 3.12.1](https://www.python.org/downloads/ );\n\nУстанавливаем среду разработки [PyCharm Community 2023.1](https://www.jetbrains.com/pycharm/download/#section=windows );\n\nЗапускаем PyCharm Community;\n\nВ нём создаем новый проект, давайте его назовём **trade_robot_moex** и укажем что создаем виртуальное окружение Virtualenv =\u003e нажимаем «Create»;\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list02.jpg)\n \nТеперь нам нужна библиотека, которая поможет брать данные с биржи MOEX, выполняем команду:\n```shell\ngit clone https://github.com/WISEPLAT/backtrader_moexalgo\n```\nона создает копию **backtrader_moexalgo** в нашем проекте\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list03.jpg)\n\nкопируем уже готовый файл **01 - Live Trade - broker Alor.py** с примером торгового робота в корень нашего проекта\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list04.jpg)\n\nтеперь клонируем дополнительные библиотеки\n\n```shell\ngit clone https://github.com/cia76/AlorPy\n```\n\n```shell\ngit clone https://github.com/cia76/BackTraderAlor\n```\n\nони нужны, для live торговли, делают связку между API брокера и Backtrader\n\nТеперь наш проект выглядит так:\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list05.jpg)\n\nПришло время установить необходимые библиотеки\n\n```shell\npy -m ensurepip --upgrade\n```\n\n\n```shell\npip install numpy pandas backtrader moexalgo requests websockets\n```\n\nТеперь меняем путь к библиотеке backtrader_moexalgo (строка 8)\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list06.jpg)\n\nСоздаем в корне проекта папку **my_config** и настраиваем файл **Config_Alor.py** для подключения к брокеру Алор через API.\n\nЭто нужно для возможности отправлять в рынок заявки на покупку и продажу акций.\n\nГде взять пример файла с конфигурацией, показано на картинке ниже:\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list07.jpg)\n\nТеперь мы готовы запустить нашего первого торгового робота в жизнь! В live режиме он будет покупать и продавать акции!\n\n## Запускаем!\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list08.jpg)\n\nНа картинке выше 1 - это получение исторических данных с MOEX, после завершения их приема, мы переходим в Live режим - 2.\n\n**Обучающее видео по работе с библиотекой backtrader_moexalgo можно посмотреть [на YouTube](https://youtu.be/SmcQF2jPxsQ ) и [на RuTube](https://rutube.ru/video/private/ba9e19f36c98d45ac9caf5b399dda6ca/?p=2T_4kwuwMz9aQAY3kFxYfQ )**\n\n\n## Торговый робот создан и работает на рынке))\n\nВот выставилась заявка на покупку.\n\n![alt text](https://raw.githubusercontent.com/WISEPLAT/imgs_for_repos/master/list09.jpg)\n\nВесь код хорошо документирован, поэтому всё становится очевидным, когда на него посмотришь поближе:\n\n```python\n# git clone https://github.com/cia76/AlorPy\n# git clone https://github.com/cia76/BackTraderAlor\n# py -m ensurepip --upgrade\n# pip install numpy pandas backtrader moexalgo requests websockets\n\nimport datetime as dt\nimport backtrader as bt\nfrom backtrader_moexalgo.backtrader_moexalgo.moexalgo_store import MoexAlgoStore  # Хранилище AlgoPack\n\n# пример live торговли для Алор\nfrom BackTraderAlor.ALStore import ALStore  # Хранилище Alor\nfrom AlorPy import AlorPy  # Работа с Alor OpenAPI V2\nfrom my_config.Config_Alor import Config  # Файл конфигурации подключения к Alor\n\n\n# Торговая система\nclass RSIStrategy(bt.Strategy):\n    \"\"\"\n    Демонстрация live стратегии - однократно покупаем по рынку 1 лот и однократно продаем его по рынку через 3 бара\n    \"\"\"\n    params = (  # Параметры торговой системы\n        ('timeframe', ''),\n        ('live_prefix', ''),  # префикс для выставления заявок в live\n        ('info_tickers', []),  # информация по тикерам\n    )\n\n    def __init__(self):\n        \"\"\"Инициализация, добавление индикаторов для каждого тикера\"\"\"\n        self.orders = {}  # Организовываем заявки в виде справочника, конкретно для этой стратегии один тикер - одна активная заявка\n        for d in self.datas:  # Пробегаемся по всем тикерам\n            self.orders[d._name] = None  # Заявки по тикеру пока нет\n\n        # создаем индикаторы для каждого тикера\n        self.sma1 = {}\n        self.sma2 = {}\n        self.rsi = {}\n        for i in range(len(self.datas)):\n            ticker = list(self.dnames.keys())[i]    # key name is ticker name\n            self.sma1[ticker] = bt.indicators.SMA(self.datas[i], period=8)  # SMA indicator\n            self.sma2[ticker] = bt.indicators.SMA(self.datas[i], period=16)  # SMA indicator\n            self.rsi[ticker] = bt.indicators.RSI(self.datas[i], period=14)  # RSI indicator\n\n        self.buy_once = {}\n        self.sell_once = {}\n\n    def start(self):\n        for d in self.datas:  # Running through all the tickers\n            self.buy_once[d._name] = False\n            self.sell_once[d._name] = False\n\n    def next(self):\n        \"\"\"Приход нового бара тикера\"\"\"\n        for data in self.datas:  # Пробегаемся по всем запрошенным барам всех тикеров\n            ticker = data._name\n            status = data._state  # 0 - Live data, 1 - History data, 2 - None\n            _interval = self.p.timeframe\n            _date = bt.num2date(data.datetime[0])\n\n            try:\n                if data.p.supercandles[ticker][data.p.metric_name]:\n                    print(\"\\tSuper Candle:\", data.p.supercandles[ticker][data.p.metric_name][0])\n                    _data = data.p.supercandles[ticker][data.p.metric_name][0]\n                    _data['datetime'] = _date\n                    self.supercandles[ticker][data.p.metric_name].append(_data)\n            except:\n                pass\n\n            if status in [0, 1]:\n                if status: _state = \"False - History data\"\n                else: _state = \"True - Live data\"\n\n                print('{} / {} [{}] - Open: {}, High: {}, Low: {}, Close: {}, Volume: {} - Live: {}'.format(\n                    bt.num2date(data.datetime[0]),\n                    data._name,\n                    _interval,  # таймфрейм тикера\n                    data.open[0],\n                    data.high[0],\n                    data.low[0],\n                    data.close[0],\n                    data.volume[0],\n                    _state,\n                ))\n                print(f'\\t - {ticker} RSI : {self.rsi[ticker][0]}')\n\n                if status != 0: continue  # если не live - то не входим в позицию!\n\n                print(f\"\\t - Free balance: {self.broker.getcash()}\")\n\n                order = self.orders[data._name]  # Заявка тикера\n                if order and order.status == bt.Order.Submitted:  # Если заявка не на бирже (отправлена брокеру)\n                    return  # то ждем постановки заявки на бирже, выходим, дальше не продолжаем\n                if not self.getposition(data):  # Если позиции нет\n                    # if order and order.status == bt.Order.Accepted:  # Если заявка на бирже (принята брокером)\n                    #     print(f\"\\t - Снимаем заявку на покупку {data._name}\")\n                    #     self.cancel(order)  # то снимаем ее\n\n                    if not self.buy_once[ticker]:  # Enter long\n                        free_money = self.broker.getcash()\n                        print(f\" - free_money: {free_money}\")\n\n                        lot = self.p.info_tickers[ticker]['securities']['LOTSIZE']\n                        size = 1 * lot  # купим 1 лот - проверку на наличие денег не будем делать, считаем что они есть)\n                        price = self.format_price(ticker, data.close[0] * 0.995)  # buy at close price -0.005% - to prevent buy\n                        # price = 273.65\n\n                        print(f\" - buy {ticker} size = {size} at price = {price}\")\n                        self.orders[data._name] = self.buy(data=data, exectype=bt.Order.Limit, price=price, size=size)\n                        print(f\"\\t - Выставлена заявка {self.orders[data._name]} на покупку {data._name}\")\n\n                        self.buy_once[ticker] = len(self)  # для однократной покупки + записываем номер бара\n\n                else:  # Если есть позиция\n                    print(self.sell_once[ticker], self.buy_once[ticker], len(self), len(self) \u003e self.buy_once[ticker] + 3)\n                    if not self.sell_once[ticker]:  # если мы еще не продаём\n                        if self.buy_once[ticker] and len(self) \u003e self.buy_once[ticker] + 3:  # если у нас есть позиция на 3-м баре после покупки\n                            print(\"sell\")\n                            print(f\"\\t - Продаём по рынку {data._name}...\")\n                            self.orders[data._name] = self.close()  # закрываем позицию по рынку\n\n                            self.sell_once[ticker] = True  # для предотвращения повторной продажи\n\n    def notify_order(self, order):\n        \"\"\"Изменение статуса заявки\"\"\"\n        order_data_name = order.data._name  # Имя тикера из заявки\n        print(\"*\"*50)\n        self.log(f'Заявка номер {order.ref} {order.info[\"order_number\"]} {order.getstatusname()} {\"Покупка\" if order.isbuy() else \"Продажа\"} {order_data_name} {order.size} @ {order.price}')\n        if order.status == bt.Order.Completed:  # Если заявка полностью исполнена\n            if order.isbuy():  # Заявка на покупку\n                self.log(f'Покупка {order_data_name} Цена: {order.executed.price:.2f}, Объём: {order.executed.value:.2f}, Комиссия: {order.executed.comm:.2f}')\n            else:  # Заявка на продажу\n                self.log(f'Продажа {order_data_name} Цена: {order.executed.price:.2f}, Объём: {order.executed.value:.2f}, Комиссия: {order.executed.comm:.2f}')\n                self.orders[order_data_name] = None  # Сбрасываем заявку на вход в позицию\n        print(\"*\" * 50)\n\n    def notify_trade(self, trade):\n        \"\"\"Изменение статуса позиции\"\"\"\n        if trade.isclosed:  # Если позиция закрыта\n            self.log(f'Прибыль по закрытой позиции {trade.getdataname()} Общая={trade.pnl:.2f}, Без комиссии={trade.pnlcomm:.2f}')\n\n    def log(self, txt, dt=None):\n        \"\"\"Вывод строки с датой на консоль\"\"\"\n        dt = bt.num2date(self.datas[0].datetime[0]) if not dt else dt  # Заданная дата или дата текущего бара\n        print(f'{dt.strftime(\"%d.%m.%Y %H:%M\")}, {txt}')  # Выводим дату и время с заданным текстом на консоль\n\n    def format_price(self, ticker, price):\n        \"\"\"\n        Функция округления до шага цены step, сохраняя signs знаков после запятой\n        print(round_custom_f(0.022636, 0.000005, 6)) --\u003e 0.022635\n        \"\"\"\n        step = self.p.info_tickers[ticker]['securities']['MINSTEP']  # сохраняем минимальный Шаг цены\n        signs = self.p.info_tickers[ticker]['securities']['DECIMALS']  # сохраняем Кол-во десятичных знаков\n\n        val = round(price / step) * step\n        return float((\"{0:.\" + str(signs) + \"f}\").format(val))\n\n\ndef get_some_info_for_tickers(tickers, live_prefix):\n    \"\"\"Функция для получения информации по тикерам\"\"\"\n    info = {}\n    for ticker in tickers:\n        i = store.get_symbol_info(ticker)\n        info[f\"{live_prefix}{ticker}\"] = i\n    return info\n\n\nif __name__ == '__main__':\n\n    # брокер Финам[FinamPy]: git clone https://github.com/cia76/FinamPy\n    # брокер Алор[AlorPy]: git clone https://github.com/cia76/AlorPy\n    # брокер Тинькофф[TinkoffPy]: git clone https://github.com/cia76/TinkoffPy\n    # ЛЮБОЙ брокер у которого есть терминал Quik[QuikPy]: git clone https://github.com/cia76/QuikPy\n\n    # пример для Алора\n    exchange = 'MOEX'  # Биржа\n    portfolio = Config.PortfolioStocks  # Портфель фондового рынка\n    apProvider = AlorPy(Config.UserName, Config.RefreshToken)  # Подключаемся к торговому счету. Логин и Refresh Token берутся из файла Config.py\n    live_prefix = 'MOEX.'  # префикс для выставления заявок в live\n    store_alor = ALStore(providers=[dict(provider_name='alor_trade', username=Config.UserName, demo=False, refresh_token=Config.RefreshToken)])  # Хранилище Alor - Подключаемся к торговому счету. Логин и Refresh Token берутся из файла Config.py\n    # - Подключение к брокеру с нашими учетными данными к выбранной бирже\n    broker = store_alor.getbroker(use_positions=False, boards=Config.Boards, accounts=Config.Accounts)  # Брокер Alor\n\n    symbol = 'SBER'  # Тикер в формате \u003cКод тикера\u003e\n    # symbol2 = 'LKOH'  # Тикер в формате \u003cКод тикера\u003e\n    store = MoexAlgoStore()  # Хранилище AlgoPack\n    cerebro = bt.Cerebro(quicknotify=True)  # Инициируем \"движок\" BackTrader\n\n    # live подключение к брокеру - для Offline закомментировать эти две строки\n    cerebro.setbroker(broker)  # Устанавливаем live брокера\n\n    # ----------------------------------------------------\n    # Внимание! - Теперь это Live режим работы стратегии #\n    # ----------------------------------------------------\n\n    info_tickers = get_some_info_for_tickers([symbol, ], live_prefix)  # берем информацию о тикере (минимальный шаг цены, кол-во знаков после запятой)\n\n    # live 1-минутные бары / таймфрейм M1\n    timeframe = \"M1\"\n    fromdate = dt.datetime.utcnow()\n    data = store.getdata(timeframe=bt.TimeFrame.Minutes, compression=1, dataname=symbol, fromdate=fromdate,\n                         live_bars=True, name=f\"{live_prefix}{symbol}\")  # поставьте здесь True - если нужно получать live бары # name - нужен для выставления в live заявок\n    # data2 = store.getdata(timeframe=bt.TimeFrame.Minutes, compression=1, dataname=symbol2, fromdate=fromdate, live_bars=True)  # поставьте здесь True - если нужно получать live бары\n\n    cerebro.adddata(data)  # Добавляем данные\n    # cerebro.adddata(data2)  # Добавляем данные\n\n    cerebro.addstrategy(RSIStrategy, timeframe=timeframe, live_prefix=live_prefix, info_tickers=info_tickers)  # Добавляем торговую систему\n\n    cerebro.run()  # Запуск торговой системы\n    # cerebro.plot()  # Рисуем график - в live режиме не нужно\n\n```\n\nВся торговая система вынесена в отдельный класс, а торговая логика находится в методе **next**.\n\nПолучается очень удобно. \n\nТеперь у вас появился код первого рабочего торгового робота, который вы можете менять под свои условия стратегий.\n\n## Важно\nИсправление ошибок, доработка и развитие кода осуществляется автором и сообществом!\n\n**Пушьте ваши коммиты!** \n\n## Условия использования\nПрограммный код выложенный по адресу https://github.com/WISEPLAT/Hackathon-MOEX-How-To-Guide в сети интернет, реализующий торговую стратегию по акциям на фондовом рынке - это **Программа** созданная исключительно для удобства работы и изучения принципов - как сделать своего торгового робота.\nПри использовании **Программы** Пользователь обязан соблюдать положения действующего законодательства Российской Федерации или своей страны.\nИспользование **Программы** предлагается по принципу «Как есть» («AS IS»). Никаких гарантий, как устных, так и письменных не прилагается и не предусматривается.\nАвтор и сообщество не дает гарантии, что все ошибки **Программы** были устранены, соответственно автор и сообщество не несет никакой ответственности за\nпоследствия использования **Программы**, включая, но, не ограничиваясь любым ущербом оборудованию, компьютерам, мобильным устройствам, \nпрограммному обеспечению Пользователя вызванным или связанным с использованием **Программы**, а также за любые финансовые потери,\nпонесенные Пользователем в результате использования **Программы**.\nНикто не ответственен за потерю данных, убытки, ущерб, включаю случайный или косвенный, упущенную выгоду, потерю доходов или любые другие потери,\nсвязанные с использованием **Программы**.\n\n**Программа** распространяется на условиях лицензии [MIT](https://choosealicense.com/licenses/mit).\n\n==========================================================================\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiseplat%2Fhackathon-moex-how-to-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwiseplat%2Fhackathon-moex-how-to-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwiseplat%2Fhackathon-moex-how-to-guide/lists"}