Перейти к основному содержимому

Копирование сделок

Зеркалируйте основной счёт cTrader на один или несколько подчинённых счётов — кроссброкерное, кросс-cID — с управлением по назначению и контролем уровня денежного эквивалента.

Концепции​

  • Профиль копирования — один основной счёт (SourceAccountId) + один или несколько пункты назначения. Жизненный цикл: Черновик → Работает → Пауза → Остановлено (Ошибка при отказе). Корневой агрегат: CopyProfile (содержит CopyDestination).
  • Пункт назначения — один подчинённый счёт + полный набор правил, как основной счёт копируется на него. Вся конфигурация — по назначению, поэтому один основной счёт может питать консервативные и агрессивные подчинённые счёта одновременно.
  • Хост механизма копирования — рабочий процесс профиля (CopyEngineHost). Подписывается на поток исполнения основного счёта, применяет каждое событие ко всем пунктам назначения.
  • Супервизор — CopyEngineSupervisor, фоновый сервис на каждом узле. Размещает назначенные профили, самоисцеляется по кластеру (см. масштабирование).

Что зеркалируется​

Событие основного счётаДействие подчинённого счёта
Открытие позиции рыночной / рыночной-диапазонОткрыть калиброванную копию (помечена идентификатором исходной позиции)
Отложенный / стоп / стоп-лимит ордерРазместить соответствующий отложенный ордер, несущий стоп-лосс/тейк-профит основного счёта
Изменение отложенного ордераИзменить зеркалированный отложенный ордер на месте (включая его стоп-лосс/тейк-профит)
Отмена / истечение отложенного ордераОтменить зеркалированный отложенный ордер
Частичное закрытиеЗакрыть ту же часть позиции подчинённого счёта
Масштабирование (увеличение объёма)Открыть добавленный объём (опционально)
Изменение стоп-лосса / трейлинг-стопаИзменить защиту позиции подчинённого счёта
Полное закрытиеЗакрыть копию подчинённого счёта

Каждая копия помечена идентификатором исходной позиции/ордера. После переподключения хост перестраивает состояние из примирения: открывает копии, которые основной счёт держит, но подчинённый отсутствует, закрывает "сиротские" копии основной счёт больше не держит — без дублирования сделок.

Создание профиля​

Новый профиль открывает выделенную полностраничную форму (/copy-trading/new), а не диалог — набор опций достаточно большой, чтобы на телефоне и рабочем столе страница читалась лучше. Она собирает всё заранее: название профиля, исходный (основной) счёт, целевые (подчинённые) счёта (мультивыбор с кнопкой Выбрать всё; выбранный основной счёт исключён из списка подчинённых) + полный набор опций по назначению. Только счёта, связанные через cTrader Open API, доступны для выбора в качестве основного или пункта назначения — копирование размещает ордеры через Open API, поэтому вручную добавленный (только cID) счёт не может копировать и не отображается в списке; когда ничего не связано, страница показывает уведомление, указывающее на Торговые счета. Режимы размера, направление и фильтр символов отображаются в виде понятных ярлыков с поясняющей справкой для каждого режима на всплывающей подсказке управления деньгами. Каждый элемент управления содержит всплывающую подсказку, объясняющую, что он делает и как его использовать. Структурированные входные данные используют правильные проверяемые элементы управления — числа/проценты через числовые поля, режимы/направление/фильтр через выпадающие списки, фильтр символов через добавляемый/удаляемый список фишек символов и карту символов через добавляемую/удаляемую таблицу строк Источник → Назначение (× множитель) — никогда не разделённый запятыми текстовый блок. Все входные данные проверяются перед сохранением — отсутствующее имя/источник/назначение, неположительный параметр изменения размера, отрицательные/несогласованные пределы лотов, выходящий за пределы процент просадки, отсутствует включённый тип ордера или пустой фильтр символов появляются как список ошибок + блокируют сохранение. При создании профиль создаётся + каждый выбранный подчинённый добавляется с выбранными параметрами, затем страница возвращается к списку копирования сделок.

Импорт / экспорт. Весь блок параметров можно экспортировать в файл JSON и повторно импортировать для предварительного заполнения формы, чтобы настройка могла быть переиспользована в разных профилях без пересвязывания. Карта символов аналогично может быть экспортирована / импортирована как CSV файл (Источник,Назначение,МножительОбъёма) — подготовьте большую карту символов брокера в электронной таблице и загрузите её за один шаг. Те же элементы управления символами и импорт/экспорт CSV также доступны в диалоге назначения на странице копирования сделок.

Действия строк соответствуют жизненному циклу: Запуск включён только когда не работает, Остановка + Пауза только когда работает, Удаление отключено при работе + запрашивает подтверждение перед удалением профиля + пунктов назначения.

Профиль, который только что запущен, на короткое время показывает статус Starting (не зелёный Running) пока его хост загружает справочные данные и запускает первую ресинхронизацию — он ещё не зеркалирует ордеры по пунктам назначения. Он переключается на Running в тот момент, когда первая ресинхронизация завершится и механизм может копировать. Starting рассматривается как работающий для элементов управления строки (Start отключен, Stop и живые-журналы включены, Edit/Delete заблокированы), поэтому разогреваемый профиль не может быть перезапущен или отредактирован во время разогрева. Фаза разогрева отслеживается в процессе на узле, размещающем профиль; профиль, размещённый на другой реплике (или тот, который не может быть размещён — его исходные/целевые счета не связаны через cTrader Open API) показывает свой простой статус.

Опции по назначению​

Установите на странице нового профиля, в диалоге назначения на странице копирования сделок или через POST /api/copy/profiles/{id}/destinations:

  • Изменение размера (MoneyManagementMode + параметр): фиксированный лот, лот/номинальный множитель, пропорциональный баланс/капитал/свободную маржу, фиксированный риск %, фиксированный леверидж, автопропорциональный, риск-%-от-стопа (M7). Плюс пределы мин/макс лота + форс-мин-лот. Риск-от-стопа устанавливает размер пункта назначения, чтобы он рисковал настроенным процентом собственного баланса, полученным из расстояния стоп-лосса основного счёта (основной риск 2% → подчинённый авто-риск 2%): лоты = баланс×% ÷ (расстояниеСтопа × размерКонтракта). Основной счёт откроется без стоп-лосса не имеет расстояния для изменения размера → использует настроенный лот отката максимального риска (M7) если установлен, иначе пропущен (без_стоп_лосса) не угадан. Пропорциональное-капитал/свободная маржа размер от реального счёта капитал (баланс + Σ плавающая P&L, полученный по cTrader Open API который не доставляет капитал), не простой баланс — поэтому основной счёт, сидящий на открытой прибыли/убытке, правильно устанавливает размер копий. Использованная маржа не раскрыта API примирения, поэтому свободная маржа рассматривается как капитал (честный прокси доступных средств); другие режимы читают баланс + пропускают лишний раунд переоценки в круговую.
  • Фильтр направления: оба / только длинные / только короткие. Обратный: переворот стороны (+ своп SL↔TP) для контрарного копирования.
  • Только управление (Игнорировать-новые-сделки / Закрытие-только): отразить закрытия, частичные закрытия + защитные изменения на уже скопированных позициях, но откройте нет новых позиций/отложенных ордеров (пропущен только_управление). Используйте, чтобы закрыть пункт назначения без удаления существующих копий.
  • Синхро-открытие-при-запуске / Синхро-закрытие-при-запуске (по умолчанию включено): при первой ресинхронизации профиля открыть ли копии для существующих ранее позиций основного счёта, + закрывать ли копии основной счёт закрыл в то время как профиль был остановлен. Оба применяются только в начале — переподключение среди работы всегда полностью примирено, поэтому рассинхронизация восстанавливается независимо.
  • Карта символов + фильтр символов (белый список / чёрный список). Каждый элемент карты символов несёт опциональный множитель объёма для каждого символа (переопределение cMAM для каждого символа) масштабирования размера копии для этого символа поверх изменения размера пункта назначения (1 = без изменений). Вся карта импортируется/экспортируется как CSV (GET …/symbol-map.csv, PUT …/symbol-map/csv; столбцы Источник,Назначение,МножительОбъёма) — каждая строка проверяется через доменные объекты значений, поэтому неправильный файл не может произвести неправильную карту.
  • Окно торговых часов (C18) — ежедневное окно UTC для пункта назначения (старт/конец минут-дня, конец исключительно; старт == конец = весь день). Новые открытия вне окна пропущены (торговые_часы); окно с старт > конец переворачивает прошлую полночь (например, 22:00–06:00). Существующие позиции остаются управляемыми.
  • Фильтр метки источника (C18, эквивалент cTrader фильтра магического номера MT) — когда установлен, копировать только основные сделки чей ярлык точно совпадает (например, сделки одного бота или только ручные ярлыки); иначе пропущен (метка_источника). Пусто = копировать всё. Перенесено на ExecutionEvent.SourceLabel из позиции/ордера основного счёта TradeData.Label, уважено и при ресинхронизации.
  • Защита счёта (ZuluGuard / Глобальная защита счёта) — следите за живым капиталом пункта назначения (баланс + Σ плавающая P&L, опрашиваемый каждые CopyDefaults.EquityGuardInterval) против пола StopEquity и/или опционального потолка TakeEquity. При нарушении применить режим: ТолькоЗакрытие (остановить новые копии, продолжить управление существующими), Заморожено (остановить открытие), СпродатьВсё (закрыть каждую копию на пункте назначения немедленно). Однажды срабатываемо, пункт назначения зафиксирован — нет новых открытий пока хост не перезагрузится — + поднято оповещение CopyAccountProtectionTriggered. СпродатьВсё требует StopEquity; TakeEquity должен находиться выше StopEquity. Оговорка об отсутствии гарантии: продажа использует рыночное исполнение — как эквивалент каждого конкурента, не может гарантировать цену заполнения на быстром/разрывистом рынке.
  • Панель паники "Уплотнить всё" (C8) — POST /api/copy/profiles/{id}/flatten немедленно закрывает каждую скопированную позицию на каждом пункте назначения + блокирует от новых открытий. Маршрутизируется кросспроцесс: API установить флаг, супервизор доставляет работающему хосту (переиспользуя канал ротации токена), который уплотняет на месте; флаг очищен, поэтому срабатывает ровно один раз (CopyFlattenAll оповещение). Пользователь затем паузирует/останавливает профиль.
  • Охрана правил пропфирм (C7) — правоприменение правил пропфирм копировальщики пользователи просят. На пункт назначения, ежедневная шапка потерь (потеря от открытия капитала дня) и/или трейлинг-просадка лимит (потеря от пиковой живой капитала), оба в валюте депозита. При нарушении пункт назначения автоматически уплотняется (каждая копия закрывается) + заблокирован остаток UTC дня (новые открытия пропущены блокировка_пропфирм); CopyPropRuleBreached оповещение срабатывает. Блокировка очищается когда UTC день переворачивает (базовый/пиковый капитал переснимается). Акции тот же живой-капитал опрос как защита счёта.
  • Дрожание исполнения (C11, по умолчанию выключено) — случайная задержка 0..N мс перед размещением каждой копии, чтобы рассинхронизировать почти идентичные временные метки ордеров по собственным счётам пользователя. Оговорка о соответствии: помощь пропфирмам, которые разрешают копирование — не инструмент для уклонения от фирмы, которая запрещает; оставаться в пределах правил вашей фирмы — ваша ответственность.
  • Блокировка конфигурации (C9) — заморозить параметры пункта назначения на период (POST …/destinations/{id}/lock с минутами). Пока заблокирован, пункт назначения не может быть удалён (агрегат отклоняет с CopyDestinationConfigLocked) — преднамеренная защита от импульсивных изменений во время просадки. Блокировка автоматически истекает на его временной метке.
  • Предварительное оповещение о согласованности (C10) — предупредить (один раз за UTC день) когда ежедневная прибыль пункта назначения достигает настроенного процента открытия капитала дня (CopyConsistencyThresholdApproaching), чтобы правило согласованности пропфирм уважалось до срабатывания. Прибыль-сторона, независимо от блокировки убытков-стороны; работает с того же дневного базовой линии как охрана правил пропфирм.
  • Фильтр типа ордера — выберите ровно какие основные типы ордеров копировать: рыночный, рыночный-диапазон, лимит, стоп, стоп-лимит (CopyOrderTypes флаги; по умолчанию все). Селективность в стиле cMAM.
  • Копировать SL / Копировать TP — зеркалировать стоп-лосс / тейк-профит основного счёта, или управлять защитой независимо. Применяется как к открытым позициям так и к лежащим отложенным ордерам — лимит/стоп/стоп-лимит копия размещается и амендируется со стоп-лоссом/тейк-профитом ордера основного счёта (свопнутые под Reverse), поэтому защита прикреплена в момент заполнения отложенного, не только после.
  • Копировать трейлинг стоп, зеркалировать частичное закрытие, зеркалировать масштабирование — каждый независимо переключаемый.
  • Копировать истечение отложенного (по умолчанию включено) — зеркалировать временную метку Good-Till-Date истечения отложенного ордера основного счёта.
  • Копировать слипаж основного счёта (по умолчанию включено) — для рыночной-диапазон + стоп-лимит ордеров, размещать ордер подчинённого точного слипажа основного счёта в пипсах (базовая цена взята из живого спота подчинённого).
  • Охраны: максимальная просадка %, ежедневная шапка потерь, максимальная задержка копирования, фильтр слипажа (пропустить копию если цена подчинённого сдвинулась больше чем N пипсов от входа основного). Максимальная задержка копирования измеряется против реальной временной метки сервера события основного (ExecutionEvent.ServerTimestamp) через вводимый TimeProvider: сигнал старше настроенного макс-лага пропущен, поэтому устаревшая копия никогда не размещена поздно (ранее задержка всегда ноль + охрана мертва).
  • SL/TP нормализация точности (M6) — скопированные стоп-лосс/тейк-профит цены округлены до назначения символа цифровой точности перед изменением (на позициях и размещении/амендировании отложенного ордера), поэтому цена основного счёта с более тонкой точностью (или кросс-брокерское несовпадение цифр) никогда не срабатывает сервером INVALID_STOPLOSS_TAKEPROFIT.
  • Выключатель цепи отказа / Охрана последователя (G8) — пункт назначения отклоняющий CopyDefaults.RejectionBudget открытия подряд срабатывается: нет новых открытий для окна охлаждения (CopyDestinationTripped оповещение срабатывает), остановка шторма отказа от молотка (пропфирм) счёта. Существующие позиции по-прежнему управляются + закрыты пока срабатываемо; выключатель авто-переустанавливается после охлаждения + успешного копирования очищает счётчик.
  • Потолок санитарности лота (C14) — абсолютный максимум размера копии и/или множественность основного счёта шапка. Вычисленная копия превышающая абсолютную шапку, или превышающая N× размер лота основного счёта, жёсткий-заблокирован (отображённый как санитарность_лота пропуск, считается на cmind.copy.skipped) не размещён — защищает от катастрофически-переразмер класс (0.23-лот основной превращающийся в 3 лота на каждого получателя через убегающий множитель или ошибку округления). Оба размера по умолчанию 0 (отключено).

Надёжность и граничные случаи​

Механизм построен для реальности что всё может выйти из строя в любой момент:

  • Тайм-аут корреляции заполнения рабского отложенного (C13) — зеркалированный подчинённый отложенный чей основной отложенный исчез (ни покоящейся ни свежезаполненный) отменён после тайм-аута корреляции, поэтому подчинённая копия не может заполниться несоотносительно в неуправляемую позицию (CopyPendingTimedOut). Ресинхронизация также очищает заполненный отложенный сирота помеченный ордер-id.

  • Кроссброкерная раса заполнения отложенного — собственный отложенный подчинённого может заполниться (его цена попала) в небольшое окно перед тем, как событие заполнения/отмены основного обрабатывается. Это оставляет позицию подчинённого помеченной идентификатором исходного ордера, которую канонические пути закрытия/SL-TP (ключённые по идентификатору исходной позиции) пропустили бы. На заполнении основного раннее заполнение подчинённого уходит и заменяется одной канонически-помеченной рыночной копией — так пункт назначения заканчивается ровно одной копией, никогда не удвоенной позицией; на отмене основного она закрывается напрямую (основной никогда не делал сделку). Оба действуют немедленно, не только при следующей ресинхронизации. Удар SL/TP подчинённой стороны закрывающий копию основной всё ещё держит это источник-управляемо и переоткрывается при следующем примирении (механизм зеркалирует события основного; он не потребляет исполнения со стороны пункта назначения).

  • Надёжное закрытие/уплотнение (M8) — закрытие сироты на ресинхронизации, или уплотнение на нарушении охраны, терпит позицию брокер уже закрыл (POSITION_NOT_FOUND): каждое закрытие работает независимо, поэтому один устаревший id никогда не прерывает ресинхронизацию или оставляет остаток счёта не-уплотненным.

  • Запуск с основным счётом уже в сделках — при запуске хост примирится + откроет копии для существующих позиций основного счёта.

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

  • Отказ размещения ордера — отказ на одном пункте назначения зафиксирован, никогда не блокирует другие пункты назначения.

  • Один действительный токен на cID — cTrader инвалидирует старый токен доступа cID момент выпущен новый. cMind меняет работающий токен хоста на месте (пере-оберегают на живом сокете) чтобы копирование продолжалось без прерывания потока. См. жизненный цикл токена.

Проверяемость​

Каждое действие испускает структурированное, сгенерированное источником событие журнала (LogMessages) с идентификатором профиля, cID пункта назначения, идентификаторами ордеров/позиций, + значения — ордер размещен/пропущен (с причиной), частичное закрытие, применённая защита, применён трейлинг, отложенный размещен/изменён/отменён, истечение зеркалировано, слипаж рыночный-диапазон зеркалирован, токен поменян, сводка ресинхронизации. Это след проверки для согласованности + разрешение споров.

Наряду с журналами, механизм испускает OpenTelemetry метрики на счётчик cMind.Copy (зарегистрирован в общем конвейере OTel, экспортируется по OTLP / в Azure Monitor как остальное): cmind.copy.latency (событие основного → распределение, мс), cmind.copy.dispatch.duration (вентилятор ко всем пунктам назначения, мс), cmind.copy.slippage.points, cmind.copy.placed (помечено пункто назначением), cmind.copy.skipped (помечено причиной), + cmind.copy.failed. Эти делают регрессию задержки/слипажа измеримой, не просто видимой в строке журнала — живая люкс-набор утверждает их против бюджета.

API​

  • GET /api/copy/profiles — список.
  • POST /api/copy/profiles — создать (с опциональными идентификаторами счётов назначения).
  • GET /api/copy/profiles/{id} — полный деталь включая каждый опцион пункта назначения.
  • POST /api/copy/profiles/{id}/destinations — добавить пункт назначения с полным набором опций.
  • DELETE /api/copy/profiles/{id}/destinations/{destinationId} — удалить.
  • POST /api/copy/profiles/{id}/{start|pause|stop} — жизненный цикл.

Тесты​

  • Единицы (tests/UnitTests/CopyTrading) — режимы изменения размера, фильтры решения, фильтр типа ордера, копирование истечения, слипаж рыночный-диапазон/стоп-лимит, переключатели SL/TP, частичное закрытие, изменение отложенного/отмена, запуск-с-открытием, отключение→рассинхронизация→ресинхронизация, в-месте замена токена, кросс-cID инвалидация. Работает против FakeTradingSession, cTrader-верный симулятор в памяти.
  • Интеграция (tests/IntegrationTests/CopyLive) — соотношение узлов/требование лизинга, распространение версии токена на настоящей Postgres.
  • E2E (tests/E2ETests) — раунд опций пункта назначения через API + пользовательский интерфейс, полный жизненный цикл.
  • Стресс / DST (tests/StressTests) — детерминированное симуляционное тестирование: засеянные рандомизированные рабочие нагрузки + внедрение отказов (качание сокета, отказ ордера, отказ рыночный-диапазон, ротация токена, смерть узла) ведут CopyEngineHost к покою + утверждают инварианты сходимости. См. тестирование/стресс-тестирование.md. Этот люкс-набор обнаружил + исправил реальную гонку при запуске: OnReconnected подключен до начального эталонного-нагрузки + ресинхронизации, поэтому качание сокета во время запуска может запустить вторую ресинхронизацию одновременно + испортить недопустимые параллельные словари состояния хоста — запуск загрузки + первая ресинхронизация теперь работают под _stateGate.
  • Живое — настоящие демо счёта cTrader; см. тестирование/живое-копирование-сделок.md.

См. dev-credentials.md для единственного файла учётных данных живое + E2E люкс-наборы читают.

Управление профилем и управление пунктом назначения​

Запуск/остановка являются кнопками значков на каждой строке профиля (отключена когда действие не применяется). Основные и целевые счёта показаны по номеру счёта, никогда внутреннему идентификатору. Нажатие профиля открывает диалог для управления его пунктами назначения (добавляйте/удаляйте с полным набором параметров для каждого пункта назначения).