Merge pull request #1820 from c9s/c9s/record-net-profit

FEATURE: add new migration script to record the net profit values
This commit is contained in:
c9s 2024-11-15 18:11:48 +08:00 committed by GitHub
commit 8e326d9cc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 146 additions and 7 deletions

13
doc/topics/profile.md Normal file
View File

@ -0,0 +1,13 @@
Profiling
===================
```shell
dotenv -f .env.local -- go run -tags pprof ./cmd/bbgo run \
--config ./makemoney-btcusdt.yaml \
--cpu-profile makemoney.pprof \
--enable-profile-server
```
```shell
go tool pprof http://localhost:6060/debug/pprof/heap
```

View File

@ -0,0 +1,17 @@
-- +up
-- +begin
ALTER TABLE `positions`
ADD COLUMN `net_profit` DECIMAL(16, 8) DEFAULT 0.00000000 NOT NULL
;
-- +end
-- +begin
UPDATE positions SET net_profit = profit WHERE net_profit = 0.0;
-- +end
-- +down
-- +begin
ALTER TABLE `positions`
DROP COLUMN `net_profit`
;
-- +end

View File

@ -0,0 +1,15 @@
-- +up
-- +begin
ALTER TABLE `positions`
ADD COLUMN `net_profit` DECIMAL DEFAULT 0.00000000 NOT NULL
;
-- +end
-- +down
-- +begin
ALTER TABLE `positions`
DROP COLUMN `net_profit`
;
-- +end

View File

@ -587,7 +587,7 @@ func (environ *Environment) RecordPosition(position *types.Position, trade types
log.Infof("recordPosition: position = %s, trade = %+v, profit = %+v", position.Base.String(), trade, profit)
if profit != nil {
if err := environ.PositionService.Insert(position, trade, profit.Profit); err != nil {
if err := environ.PositionService.Insert(position, trade, profit.Profit, profit.NetProfit); err != nil {
log.WithError(err).Errorf("can not insert position record")
}
@ -595,7 +595,7 @@ func (environ *Environment) RecordPosition(position *types.Position, trade types
log.WithError(err).Errorf("can not insert profit record: %+v", profit)
}
} else {
if err := environ.PositionService.Insert(position, trade, fixedpoint.Zero); err != nil {
if err := environ.PositionService.Insert(position, trade, fixedpoint.Zero, fixedpoint.Zero); err != nil {
log.WithError(err).Errorf("can not insert position record")
}
}

6
pkg/cmd/pprof.go Normal file
View File

@ -0,0 +1,6 @@
//go:build pprof
// +build pprof
package cmd
import _ "net/http/pprof"

View File

@ -7,6 +7,7 @@ import (
"runtime/pprof"
"strings"
"time"
_ "time/tzdata"
"github.com/heroku/rollrus"
"github.com/joho/godotenv"
@ -20,8 +21,6 @@ import (
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/util"
_ "time/tzdata"
)
var cpuProfileFile *os.File
@ -81,6 +80,24 @@ var RootCmd = &cobra.Command{
}()
}
enableProfileServer, err := cmd.Flags().GetBool("enable-profile-server")
if err != nil {
return err
}
if enableProfileServer {
profileServerBind, err := cmd.Flags().GetString("profile-server-bind")
if err != nil {
return err
}
go func() {
if err := http.ListenAndServe(profileServerBind, nil); err != nil {
log.WithError(err).Errorf("profile server error")
}
}()
}
cpuProfile, err := cmd.Flags().GetString("cpu-profile")
if err != nil {
return err
@ -195,6 +212,8 @@ func init() {
RootCmd.PersistentFlags().String("max-api-secret", "", "max api secret")
RootCmd.PersistentFlags().String("cpu-profile", "", "cpu profile")
RootCmd.PersistentFlags().Bool("enable-profile-server", false, "enable profile server binding")
RootCmd.PersistentFlags().String("profile-server-bind", "localhost:6060", "profile server binding")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))

View File

@ -0,0 +1,33 @@
package mysql
import (
"context"
"github.com/c9s/rockhopper/v2"
)
func init() {
AddMigration("main", up_main_addNetProfitColumn, down_main_addNetProfitColumn)
}
func up_main_addNetProfitColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
// This code is executed when the migration is applied.
_, err = tx.ExecContext(ctx, "ALTER TABLE `positions`\n ADD COLUMN `net_profit` DECIMAL(16, 8) DEFAULT 0.00000000 NOT NULL\n;")
if err != nil {
return err
}
_, err = tx.ExecContext(ctx, "UPDATE positions SET net_profit = profit WHERE net_profit = 0.0;")
if err != nil {
return err
}
return err
}
func down_main_addNetProfitColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
// This code is executed when the migration is rolled back.
_, err = tx.ExecContext(ctx, "ALTER TABLE `positions`\nDROP COLUMN `net_profit`\n;")
if err != nil {
return err
}
return err
}

View File

@ -0,0 +1,29 @@
package sqlite3
import (
"context"
"github.com/c9s/rockhopper/v2"
)
func init() {
AddMigration("main", up_main_addNetProfitColumn, down_main_addNetProfitColumn)
}
func up_main_addNetProfitColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
// This code is executed when the migration is applied.
_, err = tx.ExecContext(ctx, "ALTER TABLE `positions`\n ADD COLUMN `net_profit` DECIMAL DEFAULT 0.00000000 NOT NULL\n;")
if err != nil {
return err
}
return err
}
func down_main_addNetProfitColumn(ctx context.Context, tx rockhopper.SQLExecutor) (err error) {
// This code is executed when the migration is rolled back.
_, err = tx.ExecContext(ctx, "ALTER TABLE `positions`\nDROP COLUMN `net_profit`\n;")
if err != nil {
return err
}
return err
}

View File

@ -51,7 +51,11 @@ func (s *PositionService) scanRows(rows *sqlx.Rows) (positions []types.Position,
return positions, rows.Err()
}
func (s *PositionService) Insert(position *types.Position, trade types.Trade, profit fixedpoint.Value) error {
func (s *PositionService) Insert(
position *types.Position,
trade types.Trade,
profit, netProfit fixedpoint.Value,
) error {
_, err := s.DB.NamedExec(`
INSERT INTO positions (
strategy,
@ -63,6 +67,7 @@ func (s *PositionService) Insert(position *types.Position, trade types.Trade, pr
base,
quote,
profit,
net_profit,
trade_id,
exchange,
side,
@ -77,6 +82,7 @@ func (s *PositionService) Insert(position *types.Position, trade types.Trade, pr
:base,
:quote,
:profit,
:net_profit,
:trade_id,
:exchange,
:side,
@ -92,6 +98,7 @@ func (s *PositionService) Insert(position *types.Position, trade types.Trade, pr
"base": position.Base,
"quote": position.Quote,
"profit": profit,
"net_profit": netProfit,
"trade_id": trade.ID,
"exchange": trade.Exchange,
"side": trade.Side,

View File

@ -34,7 +34,7 @@ func TestPositionService(t *testing.T) {
ChangedAt: time.Now(),
}, types.Trade{
Time: types.Time(time.Now()),
}, fixedpoint.Zero)
}, fixedpoint.Zero, fixedpoint.Zero)
assert.NoError(t, err)
})
@ -54,7 +54,7 @@ func TestPositionService(t *testing.T) {
Exchange: types.ExchangeBinance,
Side: types.SideTypeSell,
Time: types.Time(time.Now()),
}, fixedpoint.NewFromFloat(10.9))
}, fixedpoint.NewFromFloat(10.9), fixedpoint.NewFromFloat(8.1))
assert.NoError(t, err)
})