1) Что это за программа
Portfolio Stress Lab — настольное WPF‑приложение для продвинутого инвестора/разработчика, которое подключается к Tinkoff Invest API, загружает портфель и историю цен, и позволяет интерактивно “крутить кризис” ползунками:
“Индекс −12%”
“Волатильность +40%”
“Ставка +150 б.п.”
“Корреляции → кризисные”
И мгновенно видеть:
стресс‑PnL портфеля
исторические VaR/ES (99%)
вклад каждой позиции в стресс‑PnL
Вычислительное ядро — QuantCore.Net (высокопроизводительная библиотека количественных расчётов).
---
2) Сравнение с другими решениями
Тип A: брокерские приложения/личные кабинеты
Примеры: мобильное/веб‑приложение Тинькофф, другие брокеры.
Что обычно есть:
текущая стоимость портфеля
доходность
иногда простые “риск‑показатели” в мягкой форме
новости/события
Чего почти никогда нет (или есть в сильно упрощённом виде):
интерактивные стресс‑сценарии (особенно “падение индекса на X%” + “кризис корреляций”)
VaR/ES на локальной истории по вашему портфелю
детализация вклада позиции в стресс‑PnL
прозрачность методики и возможность её менять
Почему: это юридически и продуктово сложно (“пугает пользователя”, вопросы по корректности, регуляторные риски, токсичность сценариев).
Тип B: профессиональные риск‑системы/платные платформы
Примеры:Bloomberg‑класс (без точных сравнений), риск‑платформы для институционалов, внутренние банковские системы.
Что обычно есть:
сценарии
VaR/ES
факторные модели
стресс‑тестинг
Минусы для частного/продвинутого пользователя:
дорого
сложно внедрять
заточено под институционалов
часто “не для домашнего использования”
---
2.2 Преимущество нашей программы (сильные стороны)
1) Интерактивный UX сценариев
Программа не “строит отчёт раз в день”, а даёт ползунки, которые меняют риск‑картину мгновенно. Это ключевая ценность:what‑if анализ становится живым.
2) Локальный in‑process расчёт
Нет серверной задержки, нет очередей, нет “запрос обработается через 3–10 секунд”. Все расчёты идут локально в приложении.
3) Скорость и предсказуемость вычислений
За счёт QuantCore.Net:
VaR/ES на 100k значений считается в долях миллисекунды (в ваших замерах < 0.5 ms на 100k)
факторный PnL считается батчами и хорошо масштабируется
Это позволяет UX “крутить слайдеры без лагов”.
4) Прозрачность модели
Пользователь видит, что именно считается и какие допущения приняты. Это большой плюс по сравнению с “чёрным ящиком” в брокерском приложении.
5) Безопасность данных (в рамках клиента)
Сценарии и расчёты выполняются локально; наружу уходят только запросы к Invest API. Это проще объяснить корпоративным пользователям, чем “мы грузим ваш портфель на наш сервер”.
---
2.3 Честные ограничения текущего MVP
Для обычных акций (type share) греческие (Delta/Vega/Rho) не показываются — это нормально, они относятся к опционам.
Для акций сейчас стресс‑PnL в MVP основан на простой факторной модели (market‑шок). Это “правильный кирпич”, но без сложных моделей корреляций/кривых.
История VaR/ES зависит от качества и длины загруженных свечей (период, ликвидность, пропуски).
---
3) Инструкция по запуску (от нуля до первого расчёта)
3.1 Предварительные требования
Windows (WPF)
.NET 8 runtime/SDK установлен (если вы запускаете из исходников)
Доступ к Tinkoff Invest API и токен (Personal token)
3.2 Где указать API‑ключ (токен)
appsettings.json
Откройте файл appsettings.json в блокноте и укажите:
{
«Tinkoff»:{
«Token»:«t.xxxxxxxxxxxxxxxxxxxxxx»,
«AccountId»:"",
«UseSandbox»:false
}
}
3.3 Нужно ли указывать AccountId
Нет. Если AccountId пустой, программа:
1) вызывает Users.GetAccounts
2) берёт первый аккаунт
AccountId нужен только если у вас несколько счетов и вы хотите конкретный.
---
4) Как пользоваться программой (по шагам)
Кнопки
1) Load Portfolio
Что делает:
подключается к Invest API с вашим токеном
загружает позиции (shares/bonds/etfs/futures/options)
загружает справочники инструментов (для тикеров/названий)
загружает last prices для инструментов с FIGI и для базовых активов опционов
строит список позиций в таблице
Что вы увидите:
Status:“Loaded positions:N”
Таблица заполнится строками
Если ошибка:
Unauthenticated → неверный токен/нет прав/пробелы в токене
ResourceExhausted → слишком большой ответ (вы уже исправили увеличением MaxReceiveMessageSize)
2) Load History (VaR/ES)
Что делает:
загружает дневные свечи (CandleInterval.Day) за HistoryDays (по умолчанию 180)
берёт не все инструменты, а только топ‑N по величине (MaxHistoryInstruments, например 50)
строит ряд дневного PnL портфеля:
— для каждого дня t:PnL[t] = Σ (Close_i[t] — Close_i[t-1]) * Quantity_i
включает расчёт VaR/ES
Что вы увидите:
VaR(99%) и ES(99%) перестанут быть —
Notes покажет, сколько инструментов реально использовано для истории
Зачем это нужно:
VaR/ES — это “исторический риск” (на основе реальных дневных движений).
3) Recalculate
Что делает:
пересчитывает стресс‑PnL и таблицу вкладов по текущим положениям ползунков
если история загружена — пересчитывает VaR/ES (с учётом “Correlation crisis”)
На практике вам часто не нужно нажимать эту кнопку: слайдеры уже вызывают пересчёт автоматически. Кнопка полезна, если вы хотите “пересчитать после загрузки/изменений”.
---
5) Ползунки (смысл каждого)
1) Index shock (%)
Пример:−12% означает “рынок/базовый актив падает на 12%”.
Как влияет:
На акции/ETF/фьючерсы: даёт основной вклад в стресс‑PnL.
На опционы: используется как шок базового актива (spot).
2) Volatility shock (%)
Пример:+40% означает “волатильность выросла на 40% относительно базовой”.
Как влияет:
На опционы: меняет sigma в Black‑Scholes и влияет на цену/vega‑часть.
На акции в MVP напрямую не влияет (пока нет модели “vol → price”).
3) Rate shock (bps)
Пример:+150 bps означает “ставка +1.50%”.
Как влияет:
На опционы: меняет r и влияет на цену/rho.
На акции/ETF в MVP напрямую не влияет.
4) Correlation crisis (0..1)
Это UX‑ручка “насколько кризисно”.
Как влияет сейчас (упрощённо, но полезно):
усиливает стресс‑PnL множителем (1 + 0.25 * crisis)
усиливает исторический ряд PnL перед VaR/ES множителем (1 + 0.8 * crisis)
---
6) Таблица позиций (что означает каждый столбец)
Ticker — тикер инструмента (из справочника)
Name — название инструмента
Type — тип: например share,bond,etf,future,option
Qty — количество (баланс)
Price — last price (для некоторых инструментов может быть —, например опционы без FIGI)
Value — текущая оценка позиции (Price × Qty). Для опционов в MVP может быть — (если мы используем только теоретическую оценку в расчёте, но не выводим её как Value)
Stress PnL — вклад этой позиции в стресс‑PnL при текущих ползунках
Delta / Vega / Rho — показываются только если позиция распознана как option и у неё есть:
— StrikePrice
— ExpirationDate
— BasicAssetPositionUid → найден underlying → есть spot
— не истёк срок до экспирации
---
7) Что это даёт “в жизни”
Вы видите не только “текущий профит/убыток”, а “что будет если завтра рынок -X%”.
Вы видите риск хвоста (VaR/ES) по вашему портфелю.
Вы видите вклад каждой позиции — что именно создаёт риск/прибыль в сценарии.
---
8) Частые проблемы и решения
Unauthenticated 40003
неверный токен
токен с пробелом/переносом
токен не от Invest API
env var TINKOFF_TOKEN переопределяет appsettings
ResourceExhausted maximum message size
слишком большой ответ gRPC (справочники, особенно опционы)
решение: увеличить MaxReceiveMessageSize (вы это уже сделали)
VaR/ES = “—”
вы не нажали Load History
по инструменту мало свечей (менее 20)
инструмент не попал в топ‑N выбранных для истории
---
9) Почему этот продукт “не дают брокеры”
Потому что стресс‑лаборатория:
поднимает юридические/репутационные вопросы (“вы пугаете клиентов”)
требует объяснимости модели и оговорок
рассчитана на продвинутых пользователей
Доступно бесплатно (благодарность приветствуется — кошелёк для доната в программе) — скачать -
https://disk.yandex.ru/d/vWqxHoMWBFI1eg
Поэтому предложение. Было бы здорово, если бы можно было оценить портфель без привязки к брокеру.
Понятно, что в этом случае все необходимые данные придется подготовить самостоятельно в определенном формате. На вскидку: состояние портфеля, возможно прошлые сделки (не уверен), котировки по инструментам и т.д.
По крайне мере по акциям, ETF и облигациям это возможно сделать, если есть интерес.
А в целом, удачи в проектах!
По мне, проще сделать универсальный импорт необходимых данных из подготовленных пользователем файлов, чем разбираться с АПИ брокеров.
А формат файлов описать, например, в виде примеров и минимума комментариев.
На мой взгляд, такая возможность заметно расширит круг возможных пользователей программы.
спасибо за развёрнутый и технически насыщенный комментарий.
Это редкий уровень погружения — ценю.
Коротко: ты прав в том, что знаешь. Но не в том, что домысливаешь.
Давай по пунктам — без перехода на личности, только инженерия.
1️⃣ GPU быстрее CPU — это не универсальная истина
Ты исходишь из того, что если задача «считает числа», то GPU всегда выигрывает.
Это ошибка обобщения.
GPU эффективен, когда:
Batch size — тысячи–миллионы элементов
Вычисления однородны (SIMT-стиль)
Передача данных не доминирует над вычислениями
QuantCore.Net решает задачи, где GPU проигрывает:
✅ Бэктестинг одной стратегии — CPU: 0.3 мс, GPU: 0.3 мс + 50 мс transfer.
✅ Риск-метрика по 500 инструментам в реальном времени — CPU укладывается в микросекунды, GPU даже не успевает стартануть.
✅ Интерактивный семантический поиск — 1 запрос, 1 вектор, 10 кандидатов → GPU не нужен.
Вывод:
2️⃣ FPGA — нишевый инструмент, а не серебряная пуля
Ты говоришь:
Да, в HFT — берут.
Но давай посмотрим на рынок квантитативного софта, а не на 50 фирм в Чикаго.
✅ QuantCore.Net — не для HFT.
✅ QuantCore.Net — для всех остальных.
Условный:
инвестиционный фонд на $500 млн AUM,
проп-трейдер с 10 стратегиями,
банковский риск-департамент,
edtech-платформа по финансам.
У них нет:
FPGA-инженеров
бюджета на Verilog/VHDL
времени перепрошивать логику каждый день
У них есть:
.NET-разработчики
Visual Studio
NuGet
QuantCore.Net даёт им 80% производительности HFT-решения за 1% цены.
Это инженерный компромисс, а не «непонимание матчасти».
3️⃣ «Никому не нужно считать триллионы опционов каждый тик» — абсолютно верно
Но мы так и не делаем.
QuantCore.Net не про «триллионы несуществующих опционов».
QuantCore.Net про:
✅ Греки за 5 микросекунд
✅ Монте-Карло для 1000 симуляций
✅ 50+ техиндикаторов на одном тике
✅ Бэктестинг 10-летней истории за 2 секунды
✅ Встраиваемый RAG для аналитических запросов
Это реальные задачи, которые каждый день решают тысячи инженеров.
И да, C# с SIMD справляется с ними быстрее, чем Python + NumPy + обвязка, и без необходимости тащить CUDA-зависимости.
4️⃣ «Самооценка vs реальность» — давай сверим реальность
Ты говоришь:
Да.
Поэтому они и приходят к нам.
Потому что мы не продаём им «FPGA за $50k/мес».
Мы продаём .NET-библиотеку за $499/мес, которая:
Работает сразу (без команд железячников)
Интегрируется в их существующий код
Даёт 95% нужной производительности
Не требует переписывать бэктестер на CUDA
Это и есть «контакт с реальностью».
Реальность говорит:
5️⃣ Про «вызов принят»
Ты написал:
Ок.
Вот простой, воспроизводимый бенчмарк:
📌 Задача:
Рассчитать 50 технических индикаторов (SMA, EMA, RSI, MACD, Bollinger)
по 10 000 свечек для 1 инструмента.
1000 раз подряд.
Измеряем latency 99-го перцентиля.
📌 Сравнение:
QuantCore.Net (C#, SIMD)
Python + NumPy + Ta-Lib
CUDA-реализация (любая, хоть руками)
Я гарантирую:
GPU будет медленнее на transfer-е
Python — медленнее на порядок
QuantCore.Net — в лидерах
Если хочешь — я выложу тестовый стенд в открытый доступ.
Будет честно.
🧠 Резюме для тех, кто дочитал
__rtx — прав в узкой нише HFT.
__rtx — неправ, когда экстраполирует эту нишу на всю индустрию.
QuantCore.Net — не «поделка с завышенной самооценкой».
Это целенаправленное, экономически обоснованное решение для огромного рынка .NET-разработчиков в финансах.
И, судя по количеству загрузок и платящих клиентов, этот рынок нас услышал.
Спасибо за диалог.
Если хочешь — продолжим в формате открытого бенчмарка.
Я — за прозрачность.
Я — за прозрачность.
спасибо, что подтолкнули к прозрачности.
Мы опубликовали бенчмарк. Код воспроизводим. Методология — BenchmarkDotNet, 20 итераций, P95/P99, MemoryDiagnoser.
Никаких «маркетинговых допущений». Только инженерия.
Давай разберём только цифры, без лирики.
1️⃣ Твой главный тезис рассыпается при взгляде на E2E-результаты
Ты утверждал:
Смотрим на E2E_Price_AoS_To_Array:
44 наносекунды на опцион.
Вопрос тебе, как инженеру:
❓ Какое GPU-решение с учётом transfer, запуска ядер и округления физически способно обработать один опцион быстрее 44 нс?
Ответ: никакое.
Потому что 44 нс — это уже околопредельная скорость:
доступ к памяти L1/L2
вычисление
d1,d2Math.Expвозврат результата
GPU сюда даже не успевает передать первый байт.
📌 Вывод: твоя критика относилась к задаче, которую мы не решаем.
А в задаче, которую мы реально решаем, GPU неконкурентоспособен.
2️⃣ Throughput: 1 млн опционов за 41 мс — почему это важно
Ты говорил:
Абсолютно верно.
Но 1 млн опционов за 41 мс — это не про «триллионы».
Это про:
✅ Бэктестинг многолетней истории по тысячам инструментов
✅ Риск-метрики по крупному портфелю в реальном времени
✅ Монте-Карло с миллионами симуляций
И главное:
Это чистый .NET, без:
Python-прослоек
CUDA-зависимостей
пересылки данных
драйверных проблем
отдельной инфраструктуры
41 мс — и результат уже в массиве, готовом к использованию.
📌 Вывод:
GPU может быть быстрее на бумаге.
Но в реальном .NET-приложении, где данные уже в управляемой памяти, а результат нужен там же —
QuantCore.Net выигрывает по совокупности факторов.
3️⃣ Про «вызов принят» — теперь твой ход
Ты написал:
Ок. Пример есть.
Код лежит в открытом репозитории:
🔗 https://github.com/likeslines-maker/QuantCore.Net/tree/main/Benchmarks.Latency
Теперь мы ждём от тебя:
GPU-реализацию той же задачи (Black–Scholes, 1 млн опционов, SoA, double precision)
Бенчмарк с замером полного цикла:
host → device transfer
вычисление
device → host transfer
Метрики: P95, P99, аллокации (если применимо)
Никаких «FPGA — это ракета».
Никаких «а если опустить точность».
Только честное A/B-сравнение.
Ты говоришь, что GPU кратно быстрее, — докажи кодом и цифрами.
4️⃣ Резюме (только по бенчмарку)
✅ E2E-латентность: 44 нс/опцион — физический предел. GPU здесь бесполезен.
✅ Throughput: 1 млн опционов за 41 мс — инженерно значимый результат в чистом .NET.
✅ Бенчмарк открыт: код, методология, данные — всё доступно для проверки.
✅ Теперь слово за тобой: покажи GPU-решение, которое быстрее в этом же сценарии.
Без хайпа. Без FPGA.
Только код, бенчмарк и цифры.
Ждём.
Про «трансфер считать неверно» Мы как раз закрываем это двумя режимами, чтобы больше не спорить словами: A) GPU compute‑only: данные уже на device, меряем только kernel time (с синхронизацией). Тут GPU и должен выигрывать. B) GPU end‑to‑end:H2D + kernel + D2H. Это реальный сценарий для .NET, когда данные и потребитель результата на CPU.
Про «бэктест 20–30 млн тиков < 1 сек» Верю, но это другой workload. Чтобы сравнение было честным, давай сравнивать один и тот же: Black–Scholes,double,SoA,1,000,000 опционов,output на host (как в нашем репо).
Фиксируем протокол (чтобы не спорить о методологии)
CPU baseline: наш THROUGHPUT_PriceBatch_1M_SoA
GPU compute‑only:kernel time
GPU end‑to‑end: полный цикл host→device→host
одинаковый генератор входов
отчёт: код + команды запуска + версии SDK/драйверов + железо
метрики:mean + P95/P99 (или эквивалентно по вашей системе замера)
Как выложишь свой вариант — запускаем и обсуждаем цифры, не мнения.
1) Ты ушёл от задачи
Мы публиковали бенч Black–Scholes (double,1 млн,SoA) и end‑to‑end latency на N=500/5k/50k.
Ты принёс техиндикаторы. Это другой workload (ветвления, зависимости по времени, другая арифметика).
Тут нечего “сравнивать” с нашим BS — это просто другая задача.
Если хочешь закрыть именно спор — сделай GPU‑версию того же BS‑батча, и всё.
2) В твоём коде GPU‑замер уже “подкручен” в свою пользу
Ты считаешь “Speedup” как:
CPU:clock() на весь расчёт
GPU: только kernel time (cudaEventElapsedTime)
Но при этом:
копирование H2D/D2H у тебя не входит в gpu_time,
а CPU‑время включает всё.
Это не “не нужно усложнять”, это просто разные числа.
Если хочешь сравнивать “как реально используется” — нужно мерять одинаковый путь:
данные на CPU → результат на CPU. Либо честно писать два режима:kernel‑only и end‑to‑end.
3) Твой GPU‑kernel логически некорректен для части индикаторов
EMA “в лоб” параллельно по свечам не считается без префикс‑алгоритмов/сканов, потому что у EMA зависимость от предыдущего значения.
У тебя там прямо комментарий “костыль через shared memory в реальном коде”. То есть пример не закончен как корректная реализация.
4) Про “перцентили не нужны”
Если речь про latency и стабильность (реальные сервисы), то хвосты важны. Среднее часто “красивое”, а P95/P99 показывает джиттер.
Но ок — можно и без них: пусть будет минимум/среднее/максимум на серии прогонов. Главное — чтобы сравнивали одно и то же.
---
Чтобы всем было понятно (без американизмов), предлагаю так:
1) Берём одну и ту же задачу (Black–Scholes, как в нашем репо).
2) Замеряем два числа:
— kernel‑only (чистая мощность GPU)
— полный цикл “данные на CPU → результат на CPU” (как реально используется в .NET)
3) Публикуем код + одну команду запуска + железо.
Всё. Никаких сложных терминов.
Сейчас мяч у тебя: сделай GPU‑реализацию нашего BS‑батча 1 млн double и покажи 2 времени (kernel и полный цикл).
Если будет быстрее — супер, мы это прямо так и напишем:GPU выигрывает по throughput,CPU — по in‑process latency и простоте интеграции.
И да — фраза “нет равных” действительно была слишком широкая. Корректнее:
“одни из лучших результатов на CPU/.NET для in‑process batch+latency”. Это и доказывает наш бенч.
_____rtx,![]()
смешно получилось
__rtx, по вашей дискуссии мне искусственный вот такое подкинул:
__rtx, у меня пока не хватает технического уровня, чтобы полноценно использовать все описанные вами штуки. Честно говоря, я даже не до конца понимаю, под какие задачи в уже работающей у меня инфраструктуре это можно было бы применить.![]()
Тем не менее дискуссия у вас с автором получилась объёмная и интересная, надеюсь, всё успел дочитать)
__rtx, да, у меня почти всё с достаточно длительным временем удержания (по моим меркам) и в основном трендовое, поэтому скорость и ордербук действительно не критичны. 50-100+ мс за глаза. Внутри дня более активная торговля у меня только в «боковике» или при резкой смене направления инструмента![]()
Тем не менее, все эти вещи хотя бы в общих чертах знать считаю совсем не лишним, в силу своей любознательности.
вот как раз свежий пост коллеги в алговетке этому и посвящен smart-lab.ru/blog/1265758.php. Тема интересная. Трейдер Bascomo раньше о подобном много писал, больше не пишет вроде, или я в чс может у него.