trengin

package module
v2.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2024 License: MIT Imports: 8 Imported by: 4

README

trengin

TRading ENGINe

Lint Status Test Status Go Report Card codecov

A golang library to build an automated trading robot. It provides the ability to separate trading strategy logic and interaction with broker.

Contents

Installing

go get github.com/evsamsonov/trengin/v2

How to use

Import the package.

import "github.com/evsamsonov/trengin/v2"

Create an Engine instance passing implementations of Strategy and Broker and call Run.

tradingEngine := trengin.New(strategy, broker)
tradingEngine.Run(context.TODO())

Main types

Name Description
Engine Trading engine
Strategy Interface of trading strategy
Broker Interface of interaction with broker
Runner Сan be implemented in the Broker to starts background tasks such as tracking open position
Actions Channel for sending trading actions
Position Trading position
PositionClosed Channel for receiving a closed position

How to implement Strategy

type Strategy interface {
	Run(ctx context.Context, actions Actions) error
}

The Run method should implement trading strategy logic. It can contain analysis of current data, opening and closing positions, tracking current positions, modifying conditional orders. You can send OpenPositionAction, ClosePositionAction, ChangeConditionalOrderAction in actions channel.

OpenPositionAction

Opening a trading position.

Constructor: NewOpenPositionAction

Arguments Description
figi Financial Instrument Global Identifier
positionType Position type (long or short)
quantity Quantity in lots
stopLossOffset Stop loss offset from opening price
takeProfitOffset Take profit offset from opening price
ChangeConditionalOrderAction

Changing a condition order.

Constructor: NewChangeConditionalOrderAction

Name Description
positionID Unique ID (UUID)
stopLoss New stop loss value (if 0 then leave as is)
takeProfit New take profit value (if 0 then leave as is)
ClosePositionAction

Closing a position.

Constructor: NewClosePositionAction

Name Description
positionID Unique ID (UUID)

An example of sending an action and receiving the result.

sendActionOrDone := func(ctx context.Context, action interface{}) error {
    select {
    case <-ctx.Done():
    	return ctx.Err()
    case s.actions <- action:
    }
    return nil
}

var stopLossIndent, takeProfitIndent float64 // Set your values
action := trengin.NewOpenPositionAction("figi", trengin.Long, 1, stopLossOffset, takeProfitOffset)
if err = s.sendActionOrDone(ctx, action); err != nil {
    // Handle error
}
result, err := action.Result(ctx)
if err != nil {
    // Handle error
}

How to implement Broker

type Broker interface {
	OpenPosition(ctx context.Context, action OpenPositionAction) (Position, PositionClosed, error)
	ClosePosition(ctx context.Context, action ClosePositionAction) (Position, error)
	ChangeConditionalOrder(ctx context.Context, action ChangeConditionalOrderAction) (Position, error)
}

The OpenPosition method should open a new position, return the opened position and a PositionClosed channel. It should implement tracking of the closure of the position by a conditional order. After sending the closed position to the PositionClosed, it should be closed.

The ClosePosition method should close the position. It should return the closed position.

The ChangeConditionalOrder method should modify the conditional orders. It should return the updated position.

Also, you can implement Runner interface in the Broker implementation to starts background tasks such as tracking open position.

type Runner interface {
	Run(ctx context.Context) error
}

Position

The Position describes a trading position. It contains a unique ID (UUID), primary and extra data. It can be in two states — open or closed.

The Extra is additional data should only be used for local and should not be tied to the trading strategy logic and the Broker implementation.

The Extra is additional data should only be used for local or information purposes. It should not be tied to the trading strategy logic and the Broker implementation.

Use NewPosition constructor to create Position.
The position must be created and closed in the Broker implementation.

Fields

Name Description
ID Unique identifier (UUID)
FIGI Financial Instrument Global Identifier
Quantity Quantity in lots
Type Type (long or short)
OpenTime Opening time
OpenPrice Opening price
CloseTime Closing time
ClosePrice Closing price
StopLoss Current stop loss
TakeProfit Current take profit
Commission Commission

Methods

Name Description
Close Close position. If the position is already closed it will return an ErrAlreadyClosed error
Closed Returns a channel that will be closed upon closing the position
IsClosed Position is closed
IsLong Position type is long
IsShort Position type is short
AddCommission Position type is short
Profit Profit by closed position
UnitProfit Profit on a lot by closed position
UnitCommission Commission on a lot by closed position
ProfitByPrice Profit by passing price
Duration Position duration from opening time to closing time
Extra Returns extra data by key or nil if not set
SetExtra Sets val for key
RangeExtra Executes passed function for each extra values

Callbacks on events

To perform additional actions (sending notifications, saving position in the database, etc.), the trading engine provides methods to set callbacks. The methods are not thread-safe and should be called before running the strategy.

Method Description
OnPositionOpened Sets callback on opening position
OnConditionalOrderChanged Sets callback on changing condition order position
OnPositionClosed Sets callback on closing position

Broker implementations

Name Description
evsamsonov/tinkoff-broker It uses Tinkoff Invest API https://tinkoff.github.io/investAPI/

What's next?

  • Implement the initialization of the trading engine with open positions.

Documentation

Overview

Package trengin предоставляет каркас для создания торгового робота. Определяет интерфейс Strategy и Broker, позволяя связать реализации этих интерфейсов через экземпляр Engine.

Strategy имеет возможность гибко выполнять действия по открытию новой позиции (OpenPositionAction), изменении условной заявки позиции (стоп-лосс и тейк-профит) (ChangeConditionalOrderAction) и закрытию позиции (ClosePositionAction).

Broker должен реализовывать функционал открытия сделки, отслеживания статуса условной заявки, изменения условной заявки и закрытия позиции.

Для выполнения дополнительного функционала можно устанавливать коллбеки на события изменения позиции c помощью методов OnPositionOpened, OnPositionClosed и OnConditionalOrderChanged

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrSendResultTimeout = errors.New("send result timeout")
	ErrUnknownAction     = errors.New("unknown action")
	ErrAlreadyClosed     = errors.New("already closed")
	ErrActionNotValid    = errors.New("action not valid")
)

Functions

This section is empty.

Types

type Actions

type Actions chan interface{}

Actions это канал для передачи торговых действий от Strategy к Broker Может принимать типы OpenPositionAction, ClosePositionAction, ChangeConditionalOrderAction. Неожиданные типы приведут к ошибке и завершению работы Engine

type Broker

type Broker interface {
	// OpenPosition opens a position and returns Position and PositionClosed channel,
	// which will be sent closed position.
	OpenPosition(ctx context.Context, action OpenPositionAction) (Position, PositionClosed, error)

	// ClosePosition closes a position and returns closed position.
	ClosePosition(ctx context.Context, action ClosePositionAction) (Position, error)

	// ChangeConditionalOrder changes conditional orders and returns changed position.
	ChangeConditionalOrder(ctx context.Context, action ChangeConditionalOrderAction) (Position, error)
}

Broker describes client for execution of trading operations.

type BrokerRunner

type BrokerRunner interface {
	Broker
	Runner
}

type ChangeConditionalOrderAction

type ChangeConditionalOrderAction struct {
	PositionID PositionID
	StopLoss   float64
	TakeProfit float64
	// contains filtered or unexported fields
}

ChangeConditionalOrderAction описывает действие на изменение условной заявки позиции с идентификатором PositionID. При передаче StopLoss или TakeProfit равным 0 данные значения не должны изменяться.

func NewChangeConditionalOrderAction

func NewChangeConditionalOrderAction(positionID PositionID, stopLoss, takeProfit float64) ChangeConditionalOrderAction

NewChangeConditionalOrderAction создает действие на изменение условной заявки по позиции с указанным positionID и новыми значения stopLoss и takeProfit. Если менять stopLoss или takeProfit не требуется, то нужно передать их равными 0.

func (*ChangeConditionalOrderAction) Result

Result возвращает канал, который вернет результат выполнения действия на изменения условной заявки.

type ChangeConditionalOrderActionResult

type ChangeConditionalOrderActionResult struct {
	Position Position
	// contains filtered or unexported fields
}

ChangeConditionalOrderActionResult описывает результат изменения условной заявки

type ClosePositionAction

type ClosePositionAction struct {
	PositionID PositionID
	// contains filtered or unexported fields
}

ClosePositionAction описывает действие по закрытию позиции.

func NewClosePositionAction

func NewClosePositionAction(positionID PositionID) ClosePositionAction

NewClosePositionAction создает действие на закрытие позиции с идентификатором positionID.

func (*ClosePositionAction) Result

Result возвращает результат выполнения действия на закрытия позиции.

type ClosePositionActionResult

type ClosePositionActionResult struct {
	Position Position
	// contains filtered or unexported fields
}

ClosePositionActionResult описывает результат закрытия позиции.

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine описывыет торговый движок. Создавать следует через конструктор New

func New

func New(strategy Strategy, broker Broker, opts ...Option) *Engine

New создает экземпляр Engine и возвращает указатель на него

func (*Engine) OnConditionalOrderChanged

func (e *Engine) OnConditionalOrderChanged(f func(position Position)) *Engine

OnConditionalOrderChanged устанавливает коллбек f на изменение условной заявки по позиции. Актуальная позиция передается параметром в метод f. Возвращает указатель на Engine, реализуя текучий интерфейс.

Метод не потокобезопасен. Не следует вызывать в разных горутинах и после запуска Engine

func (*Engine) OnPositionClosed

func (e *Engine) OnPositionClosed(f func(position Position)) *Engine

OnPositionClosed устанавливает коллбек f на закрытие позиции. Актуальная позиция передается параметром в метод f. Возвращает указатель на Engine, реализуя текучий интерфейс.

Метод не потокобезопасен. Не следует вызывать в разных горутинах и после запуска Engine

func (*Engine) OnPositionOpened

func (e *Engine) OnPositionOpened(f func(position Position)) *Engine

OnPositionOpened устанавливает коллбек f на открытие позиции. Актуальная позиция передается параметром в метод f. Возвращает указатель на Engine, реализуя текучий интерфейс.

Метод не потокобезопасен. Не следует вызывать в разных горутинах и после запуска Engine

func (*Engine) Run

func (e *Engine) Run(ctx context.Context) error

Run запускает стратегию в работу

type MockBroker

type MockBroker struct {
	mock.Mock
}

MockBroker is an autogenerated mock type for the Broker type

func NewMockBroker

func NewMockBroker(t mockConstructorTestingTNewMockBroker) *MockBroker

NewMockBroker creates a new instance of MockBroker. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.

func (*MockBroker) ChangeConditionalOrder

func (_m *MockBroker) ChangeConditionalOrder(ctx context.Context, action ChangeConditionalOrderAction) (Position, error)

ChangeConditionalOrder provides a mock function with given fields: ctx, action

func (*MockBroker) ClosePosition

func (_m *MockBroker) ClosePosition(ctx context.Context, action ClosePositionAction) (Position, error)

ClosePosition provides a mock function with given fields: ctx, action

func (*MockBroker) OpenPosition

func (_m *MockBroker) OpenPosition(ctx context.Context, action OpenPositionAction) (Position, PositionClosed, error)

OpenPosition provides a mock function with given fields: ctx, action

type MockBrokerRunner

type MockBrokerRunner struct {
	mock.Mock
}

MockBrokerRunner is an autogenerated mock type for the BrokerRunner type

func NewMockBrokerRunner

func NewMockBrokerRunner(t mockConstructorTestingTNewMockBrokerRunner) *MockBrokerRunner

NewMockBrokerRunner creates a new instance of MockBrokerRunner. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.

func (*MockBrokerRunner) ChangeConditionalOrder

func (_m *MockBrokerRunner) ChangeConditionalOrder(ctx context.Context, action ChangeConditionalOrderAction) (Position, error)

ChangeConditionalOrder provides a mock function with given fields: ctx, action

func (*MockBrokerRunner) ClosePosition

func (_m *MockBrokerRunner) ClosePosition(ctx context.Context, action ClosePositionAction) (Position, error)

ClosePosition provides a mock function with given fields: ctx, action

func (*MockBrokerRunner) OpenPosition

OpenPosition provides a mock function with given fields: ctx, action

func (*MockBrokerRunner) Run

func (_m *MockBrokerRunner) Run(ctx context.Context) error

Run provides a mock function with given fields: ctx

type MockStrategy

type MockStrategy struct {
	mock.Mock
}

MockStrategy is an autogenerated mock type for the Strategy type

func NewMockStrategy

func NewMockStrategy(t mockConstructorTestingTNewMockStrategy) *MockStrategy

NewMockStrategy creates a new instance of MockStrategy. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.

func (*MockStrategy) Run

func (_m *MockStrategy) Run(ctx context.Context, actions Actions) error

Run provides a mock function with given fields: ctx, actions

type OpenPositionAction

type OpenPositionAction struct {
	SecurityBoard    string // Trading mode identifier. Example, TQBR
	SecurityCode     string // Example, SBER
	FIGI             string // Financial Instrument Global Identifier
	Type             PositionType
	Quantity         int64
	StopLossOffset   float64 // Stop loss offset from the opening price. If 0 then stop loss is not set
	TakeProfitOffset float64 //  Take profit offset from the opening price. If 0 then stop loss is not set
	// contains filtered or unexported fields
}

OpenPositionAction is an action to open a position

func NewOpenPositionAction

func NewOpenPositionAction(
	figi string,
	positionType PositionType,
	quantity int64,
	stopLossOffset float64,
	takeProfitOffset float64,
) OpenPositionAction

NewOpenPositionAction creates OpenPositionAction with the given figi, type of position, quantity of lots, stop loss and take profit offsets. If offset is 0 then conditional order is not set.

func (*OpenPositionAction) IsValid

func (a *OpenPositionAction) IsValid() bool

IsValid проверяет, что действие валидно

func (*OpenPositionAction) Result

Result возвращает результат выполнения действия на открытие позиции.

type OpenPositionActionResult

type OpenPositionActionResult struct {
	Position Position
	Closed   PositionClosed // Канал, для отслеживания закрытия сделки
	// contains filtered or unexported fields
}

OpenPositionActionResult результат открытия позиции

type Option

type Option func(*Engine)

func WithPreventBrokerRun

func WithPreventBrokerRun(preventBrokerRun bool) Option

WithPreventBrokerRun returns Option which sets preventBrokerRun. The default preventBrokerRun is false

type Position

type Position struct {
	ID            PositionID
	SecurityBoard string // Trading mode identifier. Example, TQBR
	SecurityCode  string // Example, SBER
	FIGI          string // Financial Instrument Global Identifier
	Type          PositionType
	Quantity      int64
	OpenTime      time.Time
	OpenPrice     float64
	CloseTime     time.Time
	ClosePrice    float64
	StopLoss      float64
	TakeProfit    float64
	Commission    float64
	// contains filtered or unexported fields
}

Position is a trading position.

func NewPosition

func NewPosition(action OpenPositionAction, openTime time.Time, openPrice float64) (*Position, error)

NewPosition создает новую позицию по action, с временем открытия openTime и с ценой открытия openPrice. Если action невалиден, то вернет ErrActionNotValid.

func (*Position) AddCommission

func (p *Position) AddCommission(val float64)

AddCommission add commission to position

func (*Position) Close

func (p *Position) Close(closeTime time.Time, closePrice float64) (err error)

Close закрывает позицию с временем закрытия closeTime и ценой закрытия closePrice. При повторном вызове вернет ошибку ErrAlreadyClosed, время и цена закрытия в этом случае не изменится.

func (*Position) Closed

func (p *Position) Closed() <-chan struct{}

Closed возвращает канал, который будет закрыт при закрытии позиции

func (*Position) Duration

func (p *Position) Duration() time.Duration

Duration возвращает длительность закрытой сделки

func (*Position) Extra

func (p *Position) Extra(key interface{}) interface{}

Extra получает значение дополнительного поля по ключу key. Если значение не задано, то вернет nil

func (*Position) IsClosed

func (p *Position) IsClosed() bool

IsClosed returns true if position is closed

func (*Position) IsLong

func (p *Position) IsLong() bool

IsLong returns true if position is long

func (*Position) IsShort

func (p *Position) IsShort() bool

IsShort returns true if position is short

func (*Position) Profit

func (p *Position) Profit() float64

Profit возвращает прибыль по закрытой сделке. Для получения незафиксированной прибыли по открытой позиции следует использовать метод ProfitByPrice

func (*Position) ProfitByPrice

func (p *Position) ProfitByPrice(price float64) float64

ProfitByPrice возвращает прибыль позиции при указанной цене price

func (*Position) RangeExtra

func (p *Position) RangeExtra(f func(key interface{}, val interface{}))

RangeExtra применяет функцию f ко всем элементам списка Extra

func (*Position) SetExtra

func (p *Position) SetExtra(key interface{}, val interface{}) *Position

SetExtra устанавливает значение дополнительного поля с ключом key. Может использоваться для хранения дополнительных необязательных информационных данных при реализации стратегии или брокера. Не следует завязываться на эти данные при реализации логики работы Strategy или Broker. Исключение: локальное использование в рамках реализации Strategy или Broker

func (*Position) UnitCommission

func (p *Position) UnitCommission() float64

UnitCommission returns commission per volume unit

func (*Position) UnitProfit

func (p *Position) UnitProfit() float64

UnitProfit returns profit per volume unit

type PositionClosed

type PositionClosed <-chan Position

PositionClosed канал, в который отправляется позиция при закрытии

type PositionID

type PositionID uuid.UUID

func NewPositionID

func NewPositionID() PositionID

NewPositionID creates unique position ID

func (PositionID) String

func (p PositionID) String() string

type PositionType

type PositionType int
const (
	Long PositionType = iota + 1
	Short
)

func (PositionType) Inverse

func (t PositionType) Inverse() PositionType

Inverse returns inverted position type

func (PositionType) IsLong

func (t PositionType) IsLong() bool

IsLong returns true if position is long

func (PositionType) IsShort

func (t PositionType) IsShort() bool

IsShort returns true if position is short

func (PositionType) IsValid

func (t PositionType) IsValid() bool

IsValid returns true if position is valid

func (PositionType) Multiplier

func (t PositionType) Multiplier() float64

Multiplier возвращает 1 для значения Long, -1 для значения Short и 0 на любое другое значение. Может использоваться как множитель при вычислениях, которые зависят от типа позиции, например, при вычислении прибыли по позиции

type Runner

type Runner interface {
	Run(ctx context.Context) error
}

Runner can be implemented Broker client to starts background tasks such as tracking open position.

type Strategy

type Strategy interface {
	// Run запускает стратегию в работу
	Run(ctx context.Context, actions Actions) error
}

Strategy описывает интерфейс торговой стратегии. Позволяет реализовать стратегию, взаимодействуя с Engine через канал, которые возвращает метод Actions. Actions используется для отправки торговых действий. Есть закрыть канал Actions, то Engine завершит свою работу

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL