Основы Python для алгоритмической торговли
Трейдеры используют Python для создания торговых ботов, технических индикаторов, плагинов и других инструментов, помогающих в алгоритмической торговле или ручных операциях, и эта статья объясняет основы программирования на Python.
Python — это популярный высокоуровневый язык программирования общего назначения, используемый для веб-разработки, науки о данных, автоматизации и, совсем недавно, для алгоритмической торговли в cTrader. Независимо от того, создаете ли вы простых торговых ботов на основе сигналов или сложные стратегии с несколькими индикаторами, Python делает процесс быстрее, эффективнее и проще в управлении.
Алгоритмы на Python за одну минуту!
- Пользуйтесь встроенной поддержкой Python и бесшовным доступом к cTrader Algo API, ведь cTrader — единственная крупная платформа, предлагающая нативную интеграцию из коробки. Не требуются плагины, адаптеры или сложные настройки.
- Сосредоточьтесь больше на том, чего должна достичь ваша стратегия, поскольку логику становится проще собрать. Наслаждайтесь быстрой итерацией, повторно используемыми компонентами и масштабируемой производительностью.
- Разрабатывайте быстро, отлаживайте умнее и сотрудничайте без барьеров. Ваш код всегда будет адаптируемым, надежным и удобным в обслуживании.
- Получайте доступ и пользуйтесь тысячами бесплатных библиотек с открытым исходным кодом, подробными руководствами, примерами кода и сильной поддержкой сообщества по всему миру.
Переменные и типы данных
В Python переменные имеют динамическую типизацию, что означает, что вам не нужно явно объявлять их типы данных. Интерпретатор определяет тип во время выполнения на основе присвоенного значения.
Вы создаете переменные, просто присваивая им значение:
1 2 3 4 | |
Распространенные типы данных
| Тип | Описание | Пример |
|---|---|---|
int | Целые числа | 5, 100, api.StepPips |
float | Десятичные числа | 1.1234, 100.5, api.Symbol.Ask |
bool | Логические значения | True, False |
str | Строки | "EURUSD", api.Label |
list | Коллекция элементов | [1, 2, 3], [p for p in api.Positions] |
В алгоритмах cTrader переменные хранят важные данные, связанные с рыночной информацией, торговыми решениями и конфигурацией сиБота. Эти переменные часто представляют рассчитанные торговые объемы, значения индикаторов, логические флаги, названия инструментов, метки и многое другое.
Вот пример:
1 2 3 4 | |
В этом случае self.volumeInUnits — это float, используемый для размещения ордеров, а self.enoughMoney — это bool, контролирующий, следует ли продолжать открывать позиции в сеточной стратегии.
Классы и объекты
Python — это объектно-ориентированный язык программирования (ООП), предоставляющий инструменты для организации кода через классы и объекты, которые моделируют реальные сущности и поведение. Класс определяет шаблон для создания объектов, которые являются экземплярами этого класса со своими уникальными данными и поведением. Ключевые концепции описаны ниже:
- Класс определяется с помощью ключевого слова
class. - Метод
__init__(конструктор) обычно используется для инициализации состояния объекта. - Методы экземпляра определяют поведение.
- Атрибуты хранят данные, специфичные для каждого объекта.
Например, вы можете создать класс Car:
1 2 3 4 5 6 7 | |
Затем вы можете создать объекты класса Car и взаимодействовать с ними:
1 2 3 | |
В контексте cTrader
В cTrader сиБоты, индикаторы и плагины реализуются как классы, инкапсулирующие всю их логику. Алгоритмы взаимодействуют с платформой cTrader, используя специальный объект api, который предоставляет доступ к инструментам, графикам, ордерам, индикаторам и многому другому.
Вы можете создать класс SimplecBot в cTrader следующим образом:
1 2 3 | |
Класс SimplecBot включает единственный метод (on_start(self)), который выполняется один раз при запуске торгового бота. Функция api.Print записывает сообщение в лог, демонстрируя, как методы объекта инкапсулируют торговое поведение.
Каждый экземпляр класса фактически представляет собой автономный торговый алгоритм, который управляет своим собственным жизненным циклом и торговыми решениями, используя принципы ООП. В стандартном сиБоте cTrader класс может хранить данные внутреннего состояния, такие как объем, результаты индикаторов и т. д., и использовать несколько методов для управления торговой логикой.
Рассмотрим этот пример пересечения MACD, который инициализирует индикатор MACD при запуске и размещает ордер на покупку при возникновении сигнала пересечения MACD:
1 2 3 4 5 6 7 | |
Ключевое слово self
Внутри класса self ссылается на экземпляр класса и предоставляет доступ к его переменным и методам. self используется для:
- Хранения данных, таких как результаты индикаторов, объемы позиций и значения конфигурации.
- Отслеживания внутреннего состояния между различными вызовами методов, такими как
on_start(),on_tick()илиon_bar_closed().
Этот пример демонстрирует, как используется self:
1 2 3 4 | |
В этом случае self.volume хранит рассчитанный объем для использования в сделках, а self.macd хранит объект индикатора MACD, позволяя получать доступ к его значениям на протяжении всего жизненного цикла сиБота. Без self эти переменные были бы локальными для on_start() и недоступными в on_bar_closed(), где могут приниматься торговые решения.
Методы и функции
Функции — это блоки повторно используемого кода, применяемые для выполнения конкретной задачи. Когда функции определяются внутри класса, они называются методами и работают с внутренним состоянием класса через параметр self. В контексте алгоритмической торговли с cTrader методы определяют, как ваш торговый алгоритм ведет себя при различных условиях, таких как рыночные тики, закрытие баров или инициализация.
Платформа автоматически вызывает специальные методы (известные как обработчики событий) в подходящее время, например:
on_start(self) — вызывается один раз при инициализации бота.
1 2 | |
on_tick(self) — вызывается при каждом входящем рыночном тике.
1 2 | |
on_bar_closed(self) — вызывается при закрытии новой свечи/бара (идеально подходит для стратегий, основанных на времени).
1 2 3 4 | |
Пользовательские или вспомогательные методы
Чтобы избежать переписывания и дублирования кода, вы можете определить свои собственные методы. Такие пользовательские методы должны инкапсулировать общую логику, которую может повторно использовать ваш торговый робот.
Метод ниже возвращает все открытые позиции, связанные с меткой текущего сиБота, что упрощает отслеживание или закрытие позиций последовательно.
1 2 | |
Рассмотрим другой метод, который вычисляет расстояние в пипах между текущей ценой и ценой входа позиции, что критически важно для принятия решений в стратегиях на основе сетки.
1 2 | |
После определения метода вы можете вызвать его из того же класса, используя ключевое слово self. Этот подход позволяет повторно использовать логику в любом месте вашего бота без дублирования кода.
Например, после определения get_bot_positions() вы можете вызвать его внутри другого метода для закрытия всех позиций:
1 2 3 4 | |
Здесь self.get_bot_positions() вызывает вспомогательный метод, возвращая только позиции, связанные с меткой текущего бота.
Аналогично, метод get_distance_in_pips() можно использовать повторно для принятия торговых решений. Например, в стратегии сетки вы можете открыть новый ордер только в том случае, если рынок достаточно отдалился от последней позиции:
1 2 3 4 5 6 7 | |
Другие концепции
Пространства имен и импорт
Пространства имен в Python помогают организовать код и избежать конфликтов имен, группируя связанные идентификаторы (переменные, функции, классы). Импорт позволяет подключать внешние модули, библиотеки или пакеты для расширения функциональности за пределами стандартных возможностей Python.
В Python вы можете импортировать стандартные модули или пользовательские пакеты:
1 2 | |
Вы также можете импортировать конкретные функции или классы:
1 2 | |
При написании алгоритмов для cTrader на Python импорт работает несколько иначе, поскольку cTrader интегрируется с cTrader Algo API на основе .NET. Эта настройка включает мост, который позволяет коду Python взаимодействовать со сборками .NET, и это объясняет, почему типичный сиБот начинается с:
1 2 3 4 5 6 7 8 9 | |
Где:
import clrзагружает Common Language Runtime (CLR), позволяя Python взаимодействовать с библиотеками .NET.clr.AddReference("cAlgo.API")ссылается на сборку cAlgo API, которая содержит все связанные с торговлей классы, методы и объекты.from cAlgo.API import *импортирует все типы из API (например,TradeType,Color,Position).from robot_wrapper import *загружает вспомогательные функции и обертки, которые упрощают общие торговые операции.
Система пространств имен гарантирует, что:
- Встроенные имена Python (такие как
print) не конфликтуют с именами cTrader (такими какapi.Print). - Все объекты, связанные с торговлей (
api.Symbol,api.Indicators,api.ExecuteMarketOrder), поступают из пространства имен cTrader Algo API, сохраняя их организованными и отдельными. - Вы можете расширить функциональность, импортируя собственные пользовательские пакеты для работы вместе со встроенными типами cTrader.
Циклы
Циклы позволяют повторять операции над последовательностью значений или до выполнения условия. В алгоритмической торговле циклы часто используются для обработки позиций (например, закрытия, фильтрации или обновления), проверки условий по нескольким активам или индикаторам, реализации стратегий сетки или мартингейла, где требуется повторное размещение ордеров, и многого другого.
В Python итерация проста и поддерживает как циклы for (для итерации по коллекциям), так и циклы while (для повторения до изменения условия).
Вы можете написать цикл для закрытия позиций:
1 2 3 4 | |
В этом случае:
self.get_bot_positions()возвращает все позиции, принадлежащие текущему сиБоту.- Цикл
forпроходит по каждой позиции. - Совпадающие позиции закрываются с помощью
api.ClosePosition.
Рассмотрим другой цикл, который перебирает все открытые позиции сетки, закрывает их одну за другой и рекурсивно проверяет, остались ли какие-либо позиции (для безопасности в случае частичного закрытия).
1 2 3 4 5 6 | |
Условные операторы
Условные операторы управляют потоком выполнения в Python, позволяя вашему алгоритму принимать решения на основе логических выражений. Условные операторы являются основой логики стратегии, определяя, когда входить, выходить или управлять позициями.
Python поддерживает три основные условные конструкции:
if– выполняет код, когда условие истинно.elif(else if) – проверяет другое условие, если первое было ложным.else– предоставляет резервный вариант, когда ни одно условие не выполнено.
Рассмотрим условия пересечения MACD, выраженные в этом коде:
1 2 3 4 | |
Эта структура:
- Размещает ордер на покупку, когда линия MACD находится выше сигнальной линии.
- Размещает ордер на продажу, когда линия MACD находится ниже сигнальной линии.
- Пропускает торговлю, если нет четкого сигнала.
Списки
Python предоставляет мощные и лаконичные инструменты для работы с коллекциями данных, такими как сделки, цены или индикаторы. Два наиболее распространенных — это списковые включения и встроенные функции агрегации, такие как sum().
Например, вы можете написать код, который перебирает numbers и сохраняет только четные числа таким образом:
1 2 | |
Вы можете использовать списковое включение для выбора только позиций для текущего символа, создавая отфильтрованный список, который полезен в средах с несколькими символами.
1 | |
Агрегирование прибыли или объема с помощью sum() — стандартный подход в стратегиях сеточной торговли для определения момента, когда общая прибыль достигает целевого значения.
1 | |
Вы можете комбинировать фильтрацию и агрегацию таким образом:
1 2 | |
Синхронные и асинхронные операции
Python по умолчанию следует модели синхронного выполнения. Методы жизненного цикла вашего алгоритма, такие как on_start, on_tick и on_bar_closed, запускаются циклом событий платформы по одному за раз.
Вот базовое представление синхронного торгового потока:
graph TD
A(Получение сигнала) ==> B(Исполнение ордера)
B ==> C(Позиция<br>достигает TP/SL)
C ==> D(Закрытие позиции)
D ==> A В синхронных потоках любая длительная операция может заблокировать поток, потенциально задерживая следующее событие. Однако в реальных стратегиях алгоритмы обычно инициируют неблокирующие действия, такие как отправка ордера или установка стоп-лосса и тейк-профита, а затем ожидают будущих событий (таких как новый тик или бар) для обработки результатов. Эта настройка приводит к асинхронной оркестровке, даже если конструкции async/await Python не используются.
Примечание
Для большинства торговых алгоритмов явное асинхронное программирование не требуется.
cTrader управляет параллелизмом, сериализуя ваши обратные вызовы на основе событий. Каждый метод вызывается независимо и никогда не параллельно, устраняя необходимость в защите от многопоточности. Этот дизайн позволяет стратегиям реагировать на несколько торговых условий одновременно в логическом смысле, без блокировки.
В приведенном ниже примере стратегия независимо оценивает сигналы на покупку и продажу и соответствующим образом реагирует, без какого-либо перекрытия в контексте выполнения.
graph TD
A([Получение сигнала]) ==> B([Открытие<br>ордера на покупку]) & C([Открытие ордера<br>на продажу<br>для хеджирования]) ==> D([Ордер достигает<br>тейк-профита<br>или стоп-лосса])
D ==> E([Закрытие позиции])
E ==> A Даже если решения могут казаться параллельными, они обрабатываются последовательно внутренней системой очередей cTrader. Архитектура платформы направлена на предотвращение проблем параллелизма, сохраняя при этом отзывчивость торговых роботов к изменениям рынка.
