mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
positionmodifier: move functions into types.Position
This commit is contained in:
parent
9588a6f6bd
commit
4bc70820c4
|
@ -27,9 +27,9 @@ type closePositionContext struct {
|
||||||
percentage fixedpoint.Value
|
percentage fixedpoint.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type updatePositionContext struct {
|
type modifyPositionContext struct {
|
||||||
signature string
|
signature string
|
||||||
updater StrategyPositionUpdater
|
modifier *types.Position
|
||||||
target string
|
target string
|
||||||
value fixedpoint.Value
|
value fixedpoint.Value
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ type CoreInteraction struct {
|
||||||
|
|
||||||
exchangeStrategies map[string]SingleExchangeStrategy
|
exchangeStrategies map[string]SingleExchangeStrategy
|
||||||
closePositionContext closePositionContext
|
closePositionContext closePositionContext
|
||||||
updatePositionContext updatePositionContext
|
modifyPositionContext modifyPositionContext
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCoreInteraction(environment *Environment, trader *Trader) *CoreInteraction {
|
func NewCoreInteraction(environment *Environment, trader *Trader) *CoreInteraction {
|
||||||
|
@ -74,6 +74,21 @@ func filterStrategyByInterface(checkInterface interface{}, exchangeStrategies ma
|
||||||
return strategies, found
|
return strategies, found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterStrategyByField(fieldName string, fieldType reflect.Type, exchangeStrategies map[string]SingleExchangeStrategy) (strategies map[string]SingleExchangeStrategy, found bool) {
|
||||||
|
found = false
|
||||||
|
strategies = make(map[string]SingleExchangeStrategy)
|
||||||
|
for signature, strategy := range exchangeStrategies {
|
||||||
|
r := reflect.ValueOf(strategy).Elem()
|
||||||
|
f := r.FieldByName(fieldName)
|
||||||
|
if !f.IsZero() && f.Type() == fieldType {
|
||||||
|
strategies[signature] = strategy
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strategies, found
|
||||||
|
}
|
||||||
|
|
||||||
func generateStrategyButtonsForm(strategies map[string]SingleExchangeStrategy) [][3]string {
|
func generateStrategyButtonsForm(strategies map[string]SingleExchangeStrategy) [][3]string {
|
||||||
var buttonsForm [][3]string
|
var buttonsForm [][3]string
|
||||||
signatures := getStrategySignatures(strategies)
|
signatures := getStrategySignatures(strategies)
|
||||||
|
@ -397,14 +412,14 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Position updater
|
// Position updater
|
||||||
i.PrivateCommand("/setposition", "Set Strategy Position", func(reply interact.Reply) error {
|
i.PrivateCommand("/modifyposition", "Modify Strategy Position", func(reply interact.Reply) error {
|
||||||
// it.trader.exchangeStrategies
|
// it.trader.exchangeStrategies
|
||||||
// send symbol options
|
// send symbol options
|
||||||
if strategies, found := filterStrategyByInterface((*StrategyPositionUpdater)(nil), it.exchangeStrategies); found {
|
if strategies, found := filterStrategyByField("Position", reflect.TypeOf(types.NewPosition("", "", "")), it.exchangeStrategies); found {
|
||||||
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
||||||
reply.Message("Please choose one strategy")
|
reply.Message("Please choose one strategy")
|
||||||
} else {
|
} else {
|
||||||
reply.Message("No strategy supports StrategyPositionUpdater")
|
reply.Message("No strategy supports Position Modify")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}).Next(func(signature string, reply interact.Reply) error {
|
}).Next(func(signature string, reply interact.Reply) error {
|
||||||
|
@ -414,14 +429,16 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
return fmt.Errorf("strategy %s not found", signature)
|
return fmt.Errorf("strategy %s not found", signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
updater, implemented := strategy.(StrategyPositionUpdater)
|
r := reflect.ValueOf(strategy).Elem()
|
||||||
|
f := r.FieldByName("Position")
|
||||||
|
positionModifier, implemented := f.Interface().(*types.Position)
|
||||||
if !implemented {
|
if !implemented {
|
||||||
reply.Message(fmt.Sprintf("Strategy %s does not support StrategyPositionUpdater", signature))
|
reply.Message(fmt.Sprintf("Strategy %s does not support Position Modify", signature))
|
||||||
return fmt.Errorf("strategy %s does not implement StrategyPositionUpdater", signature)
|
return fmt.Errorf("strategy %s does not implement Position Modify", signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
it.updatePositionContext.updater = updater
|
it.modifyPositionContext.modifier = positionModifier
|
||||||
it.updatePositionContext.signature = signature
|
it.modifyPositionContext.signature = signature
|
||||||
|
|
||||||
reply.Message("Please choose what you want to change")
|
reply.Message("Please choose what you want to change")
|
||||||
reply.AddButton("base", "Base", "base")
|
reply.AddButton("base", "Base", "base")
|
||||||
|
@ -435,13 +452,13 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
return fmt.Errorf("%q is not a valid target string", target)
|
return fmt.Errorf("%q is not a valid target string", target)
|
||||||
}
|
}
|
||||||
|
|
||||||
it.updatePositionContext.target = target
|
it.modifyPositionContext.target = target
|
||||||
|
|
||||||
reply.Message("Enter the amount to change")
|
reply.Message("Enter the amount to change")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}).Next(func(valueStr string, reply interact.Reply) error {
|
}).Next(func(valueStr string, reply interact.Reply) error {
|
||||||
value, err := strconv.ParseFloat(valueStr, 64)
|
value, err := fixedpoint.NewFromString(valueStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reply.Message(fmt.Sprintf("%q is not a valid value string", valueStr))
|
reply.Message(fmt.Sprintf("%q is not a valid value string", valueStr))
|
||||||
return err
|
return err
|
||||||
|
@ -451,12 +468,12 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
kc.RemoveKeyboard()
|
kc.RemoveKeyboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
if it.updatePositionContext.target == "base" {
|
if it.modifyPositionContext.target == "base" {
|
||||||
err = it.updatePositionContext.updater.UpdateBase(value)
|
err = it.modifyPositionContext.modifier.ModifyBase(value)
|
||||||
} else if it.updatePositionContext.target == "quote" {
|
} else if it.modifyPositionContext.target == "quote" {
|
||||||
err = it.updatePositionContext.updater.UpdateQuote(value)
|
err = it.modifyPositionContext.modifier.ModifyQuote(value)
|
||||||
} else if it.updatePositionContext.target == "cost" {
|
} else if it.modifyPositionContext.target == "cost" {
|
||||||
err = it.updatePositionContext.updater.UpdateAverageCost(value)
|
err = it.modifyPositionContext.modifier.ModifyAverageCost(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -464,7 +481,7 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
reply.Message(fmt.Sprintf("Position of strategy %s modified.", it.updatePositionContext.signature))
|
reply.Message(fmt.Sprintf("Position of strategy %s modified.", it.modifyPositionContext.signature))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
package bbgo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate callbackgen -type PositionUpdater -interface
|
|
||||||
type PositionUpdater struct {
|
|
||||||
Position *types.Position
|
|
||||||
|
|
||||||
// Callbacks
|
|
||||||
updateBaseCallbacks []func()
|
|
||||||
updateQuoteCallbacks []func()
|
|
||||||
updateAverageCostCallbacks []func()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) UpdateBase(qty float64) error {
|
|
||||||
s.Position.Base = fixedpoint.NewFromFloat(qty)
|
|
||||||
|
|
||||||
s.EmitUpdateBase()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) UpdateQuote(qty float64) error {
|
|
||||||
s.Position.Quote = fixedpoint.NewFromFloat(qty)
|
|
||||||
|
|
||||||
s.EmitUpdateQuote()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) UpdateAverageCost(price float64) error {
|
|
||||||
s.Position.AverageCost = fixedpoint.NewFromFloat(price)
|
|
||||||
|
|
||||||
s.EmitUpdateAverageCost()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type StrategyPositionUpdater interface {
|
|
||||||
UpdateBase(qty float64) error
|
|
||||||
UpdateQuote(qty float64) error
|
|
||||||
UpdateAverageCost(price float64) error
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Code generated by "callbackgen -type PositionUpdater -interface"; DO NOT EDIT.
|
|
||||||
|
|
||||||
package bbgo
|
|
||||||
|
|
||||||
import ()
|
|
||||||
|
|
||||||
func (s *PositionUpdater) OnUpdateBase(cb func()) {
|
|
||||||
s.updateBaseCallbacks = append(s.updateBaseCallbacks, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) EmitUpdateBase() {
|
|
||||||
for _, cb := range s.updateBaseCallbacks {
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) OnUpdateQuote(cb func()) {
|
|
||||||
s.updateQuoteCallbacks = append(s.updateQuoteCallbacks, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) EmitUpdateQuote() {
|
|
||||||
for _, cb := range s.updateQuoteCallbacks {
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) OnUpdateAverageCost(cb func()) {
|
|
||||||
s.updateAverageCostCallbacks = append(s.updateAverageCostCallbacks, cb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PositionUpdater) EmitUpdateAverageCost() {
|
|
||||||
for _, cb := range s.updateAverageCostCallbacks {
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type PositionUpdaterEventHub interface {
|
|
||||||
OnUpdateBase(cb func())
|
|
||||||
|
|
||||||
OnUpdateQuote(cb func())
|
|
||||||
|
|
||||||
OnUpdateAverageCost(cb func())
|
|
||||||
}
|
|
|
@ -84,9 +84,6 @@ type Strategy struct {
|
||||||
|
|
||||||
// StrategyController
|
// StrategyController
|
||||||
bbgo.StrategyController
|
bbgo.StrategyController
|
||||||
|
|
||||||
// PositionUpdater
|
|
||||||
bbgo.PositionUpdater
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) ID() string {
|
func (s *Strategy) ID() string {
|
||||||
|
|
|
@ -59,6 +59,11 @@ type Position struct {
|
||||||
AccumulatedProfit fixedpoint.Value `json:"accumulatedProfit,omitempty" db:"accumulated_profit"`
|
AccumulatedProfit fixedpoint.Value `json:"accumulatedProfit,omitempty" db:"accumulated_profit"`
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
|
// Modify position callbacks
|
||||||
|
modifyBaseCallbacks []func(qty fixedpoint.Value)
|
||||||
|
modifyQuoteCallbacks []func(qty fixedpoint.Value)
|
||||||
|
modifyAverageCostCallbacks []func(price fixedpoint.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Position) CsvHeader() []string {
|
func (p *Position) CsvHeader() []string {
|
||||||
|
@ -195,6 +200,54 @@ func (p *Position) UnrealizedProfit(price fixedpoint.Value) fixedpoint.Value {
|
||||||
return fixedpoint.Zero
|
return fixedpoint.Zero
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModifyBase modifies position base quantity with `qty`
|
||||||
|
func (p *Position) ModifyBase(qty fixedpoint.Value) error {
|
||||||
|
p.Base = qty
|
||||||
|
|
||||||
|
p.EmitModifyBase(qty)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmitModifyBase triggers callbacks
|
||||||
|
func (p *Position) EmitModifyBase(qty fixedpoint.Value) {
|
||||||
|
for _, cb := range p.modifyBaseCallbacks {
|
||||||
|
cb(qty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyQuote modifies position quote quantity with `qty`
|
||||||
|
func (p *Position) ModifyQuote(qty fixedpoint.Value) error {
|
||||||
|
p.Quote = qty
|
||||||
|
|
||||||
|
p.EmitModifyQuote(qty)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmitModifyQuote triggers callbacks
|
||||||
|
func (p *Position) EmitModifyQuote(qty fixedpoint.Value) {
|
||||||
|
for _, cb := range p.modifyQuoteCallbacks {
|
||||||
|
cb(qty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModifyAverageCost modifies position average cost with `price`
|
||||||
|
func (p *Position) ModifyAverageCost(price fixedpoint.Value) error {
|
||||||
|
p.AverageCost = price
|
||||||
|
|
||||||
|
p.EmitModifyAverageCost(price)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmitModifyAverageCost triggers callbacks
|
||||||
|
func (p *Position) EmitModifyAverageCost(price fixedpoint.Value) {
|
||||||
|
for _, cb := range p.modifyAverageCostCallbacks {
|
||||||
|
cb(price)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type FuturesPosition struct {
|
type FuturesPosition struct {
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
BaseCurrency string `json:"baseCurrency"`
|
BaseCurrency string `json:"baseCurrency"`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user