Управление позициями

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

PositionManager

Класс PositionManager реализует интерфейс IPositionManager и является основным компонентом для расчёта текущих позиций на основе входящих сообщений.

Создание менеджера

Конструктор принимает два параметра:

var state = new PositionManagerState();
var manager = new PositionManager(byOrders: false, state);
  • byOrders = true -- позиция рассчитывается на основе изменений баланса заявок. Подходит, когда торговая система получает обновления состояния заявок, но не отдельные сделки.
  • byOrders = false -- позиция рассчитывается на основе объёмов сделок (рекомендуемый режим). Обеспечивает более точный учёт исполненных операций.

Обработка сообщений

Метод ProcessMessage принимает входящее сообщение (Message) и возвращает PositionChangeMessage при изменении позиции, или null, если позиция не изменилась:

var posChange = manager.ProcessMessage(executionMsg);

if (posChange != null)
{
    Console.WriteLine($"Позиция: {posChange.CurrentValue}");
}

IPositionManagerState

Интерфейс IPositionManagerState описывает внутреннее состояние менеджера позиций. Реализация PositionManagerState хранит информацию о текущих заявках и позициях.

Основные методы

Метод Описание
AddOrGetOrder Регистрирует новую заявку или возвращает существующую по transactionId
TryGetOrder Получает параметры заявки (инструмент, портфель, направление, баланс)
UpdateOrderBalance Обновляет текущий баланс заявки после частичного исполнения
RemoveOrder Удаляет завершённую заявку из отслеживания
UpdatePosition Обновляет позицию по инструменту и портфелю, возвращает новое значение
Clear Сбрасывает всё состояние менеджера

Пример работы с состоянием

var state = new PositionManagerState();

// Регистрация заявки
state.AddOrGetOrder(
    transactionId: 12345,
    securityId: secId,
    portfolioName: "MyPortfolio",
    side: Sides.Buy,
    volume: 100,
    balance: 100
);

// Обновление после частичного исполнения
state.UpdateOrderBalance(12345, newBalance: 60);

// Обновление позиции напрямую
var newPosition = state.UpdatePosition(secId, "MyPortfolio", diff: 40);
Console.WriteLine($"Текущая позиция: {newPosition}");

// Очистка
state.Clear();

PositionLifecycleTracker

Класс PositionLifecycleTracker отслеживает полный жизненный цикл позиций -- от открытия до закрытия (round-trip). Это полезно для анализа отдельных сделок, расчёта прибыли по каждой позиции и построения отчётов.

Основные возможности

  • История: свойство History (IReadOnlyList<ReportPosition>) содержит все завершённые round-trip позиции.
  • Событие RoundTripClosed: срабатывает при закрытии позиции (значение достигло нуля) или при развороте (смена знака позиции).
  • Метод ProcessPosition: принимает объект Position и обновляет внутреннее состояние.

Детектируемые состояния

Состояние Описание
Открытие Позиция из нуля переходит в ненулевое значение
Закрытие Значение позиции достигает нуля
Разворот Знак позиции меняется (например, с длинной на короткую)

Пример использования

var tracker = new PositionLifecycleTracker();

tracker.RoundTripClosed += report =>
{
    Console.WriteLine($"Round-trip завершён:");
    Console.WriteLine($"  Открытие: {report.OpenTime}");
    Console.WriteLine($"  Закрытие: {report.CloseTime}");
};

// Обработка обновлений позиций
tracker.ProcessPosition(position);

// Просмотр истории
foreach (var report in tracker.History)
{
    Console.WriteLine($"  {report.OpenTime} -> {report.CloseTime}");
}

PositionMessageAdapter

Класс PositionMessageAdapter представляет собой обёртку над адаптером сообщений, которая автоматически рассчитывает позиции из потока сообщений. Используется во внутренней инфраструктуре коннекторов.

Принцип работы

var innerAdapter = connector.Adapter;
var posManager = new PositionManager(byOrders: false, new PositionManagerState());
var posAdapter = new PositionMessageAdapter(innerAdapter, posManager);

Адаптер перехватывает сообщения об исполнении заявок и сделок, вызывает PositionManager.ProcessMessage и генерирует соответствующие PositionChangeMessage для вышестоящих обработчиков.

Позиции в стратегиях

В классе Strategy доступ к текущей позиции осуществляется через свойство Position:

// Текущая позиция по основному инструменту
decimal currentPosition = Position;

// Закрытие позиции
if (Position > 0)
    SellMarket(Math.Abs(Position));
else if (Position < 0)
    BuyMarket(Math.Abs(Position));

// Или через встроенный метод
ClosePosition();

Подробнее о торговых операциях в стратегиях -- в разделе Торговые операции.

См. также