TRading ENGINe
A golang library to build an automated trading robot. It provides the ability to separate trading strategy logic and interaction with broker.
- Installing
- How to use
- Main types
- How to implement Strategy
- How to implement Broker
- Position
- Callbacks on events
- Broker implementations
- What's next?
go get github.com/evsamsonov/trengin/v2
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())
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 |
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.
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 |
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) |
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
}
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
}
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 |
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 |
Name | Description |
---|---|
evsamsonov/tinkoff-broker | It uses Tinkoff Invest API |
evsamsonov/finam-broker | It uses Finam Trade API |
- Implement the initialization of the trading engine with open positions.