Skip to content

Commit

Permalink
バイアンドホールド指標の追加
Browse files Browse the repository at this point in the history
  • Loading branch information
tktk4751 committed Jan 30, 2024
1 parent 9d2f319 commit 192e659
Show file tree
Hide file tree
Showing 16 changed files with 755 additions and 414 deletions.
26 changes: 14 additions & 12 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ package main

import (
"fmt"

// "net/http"

chart "v1/pkg/charts"
"v1/pkg/strategey"
// "v1/pkg/analytics/metrics"
// "v1/pkg/db/models"
Expand Down Expand Up @@ -49,18 +45,24 @@ import (
// }
func main() {

strategey.RunBacktestDonchain()
// strategyName := "RSI"
// assetName := "SEIUSDT"
// duration := "30m"
// account := trader.NewAccount(1000)

strategey.RunBacktestRsi()
// strategyName := "B&H"
// assetName := config.AssetName
// duration := config.Dration

// fmt.Println(assetName)
// tableName := strategyName + "_" + assetName + "_" + duration

// _, err := execute.CreateDBTable(tableName)
// _, err = execute.CreateDBTable(tableName)
// if err != nil {
// log.Fatal(err)
// }

// // df, _ := strategey.GetCandleData(assetName, duration)
// df, _ := strategey.GetCandleData(assetName, duration)

// df.BuyAndHoldingStrategy(account)

// // profit, period := df.OptimizeProfitDonchain()

Expand Down Expand Up @@ -127,8 +129,8 @@ func main() {
defer fmt.Println("メイン関数終了")

// チャート呼び出し
var c chart.CandleStickChart
c.CandleStickChart()
// var c chart.CandleStickChart
// c.CandleStickChart()

// query.GetCloseData("BTCUSDT", "4h")

Expand Down
8 changes: 8 additions & 0 deletions config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@




assetName: "TIAUSDT"

duration: "5m"

2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,6 @@ require (
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.17.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
46 changes: 0 additions & 46 deletions pkg/acount/acount.go

This file was deleted.

2 changes: 1 addition & 1 deletion pkg/analytics/analytics.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"v1/pkg/execute"
)

var AccountBalance float64 = 1000.000
var initialBalance float64 = 1000.000

var s *execute.SignalEvents

Expand Down
97 changes: 46 additions & 51 deletions pkg/analytics/drawdown.go
Original file line number Diff line number Diff line change
@@ -1,62 +1,57 @@
package analytics

import (
"math"
"v1/pkg/execute"
)

type Bar struct {
High float64
Low float64
}

// MaxDrawdown関数は、与えられた取引シグナルの配列から、最大ドローダウンを計算して返す関数です。
// 引数は、execute.SignalEvents型のポインタです。
// 返り値は、float64型です。
func MaxDrawdown(signalEvents *execute.SignalEvents) float64 {
// 初期アカウントバランスを設定します。この値はテストケースに合わせて変更できます。
if s == nil {
return 0.0
}
// 累積利益を保持する変数を宣言します。初期値は0です。
var cumulativeProfit float64 = 0.0

// 最高値を保持する変数を宣言します。初期値は0です。
var maxProfit float64 = 0.0

// 最大ドローダウンを保持する変数を宣言します。初期値は0です。
var maxDrawdown float64 = 0.0

// 取引シグナルの配列をループして、累積利益と最大ドローダウンを更新します。
for _, signal := range signalEvents.Signals {
// 取引シグナルの種類に応じて、累積利益を計算します。
// 買いシグナルの場合、価格×数量分だけ累積利益を減らします。
// 売りシグナルの場合、価格×数量分だけ累積利益を増やします。
if signal.Side == "BUY" {
cumulativeProfit -= signal.Price * signal.Size
} else if signal.Side == "SELL" {
cumulativeProfit += signal.Price * signal.Size
}

// 累積利益が最高値を更新した場合、最高値を累積利益と同じにします。
if cumulativeProfit > maxProfit {
maxProfit = cumulativeProfit
}

// 累積利益が最高値から減少した場合、ドローダウンを計算します。
// ドローダウンは、最高値からの減少額を初期アカウントバランスで割ったものです。
// ドローダウンが最大ドローダウンを更新した場合、最大ドローダウンをドローダウンと同じにします。
if cumulativeProfit < maxProfit {
drawdown := (maxProfit - cumulativeProfit) / AccountBalance
if drawdown > maxDrawdown {
maxDrawdown = drawdown
}
}
}

// 最大ドローダウンを小数点第二位まで四捨五入して返します。
return math.Round(maxDrawdown) / 100
}
// // 引数は、execute.SignalEvents型のポインタです。
// // 返り値は、float64型です。
// func MaxDrawdown(signalEvents *execute.SignalEvents) float64 {
// // 初期アカウントバランスを設定します。この値はテストケースに合わせて変更できます。
// if s == nil {
// return 0.0
// }
// // 累積利益を保持する変数を宣言します。初期値は0です。
// var cumulativeProfit float64 = 0.0

// // 最高値を保持する変数を宣言します。初期値は0です。
// var maxProfit float64 = 0.0

// // 最大ドローダウンを保持する変数を宣言します。初期値は0です。
// var maxDrawdown float64 = 0.0

// // 取引シグナルの配列をループして、累積利益と最大ドローダウンを更新します。
// for _, signal := range signalEvents.Signals {
// // 取引シグナルの種類に応じて、累積利益を計算します。
// // 買いシグナルの場合、価格×数量分だけ累積利益を減らします。
// // 売りシグナルの場合、価格×数量分だけ累積利益を増やします。
// if signal.Side == "BUY" {
// cumulativeProfit -= signal.Price * signal.Size
// } else if signal.Side == "SELL" {
// cumulativeProfit += signal.Price * signal.Size
// }

// // 累積利益が最高値を更新した場合、最高値を累積利益と同じにします。
// if cumulativeProfit > maxProfit {
// maxProfit = cumulativeProfit
// }

// // 累積利益が最高値から減少した場合、ドローダウンを計算します。
// // ドローダウンは、最高値からの減少額を初期アカウントバランスで割ったものです。
// // ドローダウンが最大ドローダウンを更新した場合、最大ドローダウンをドローダウンと同じにします。
// if cumulativeProfit < maxProfit {
// drawdown := (maxProfit - cumulativeProfit) / AccountBalance
// if drawdown > maxDrawdown {
// maxDrawdown = drawdown
// }
// }
// }

// // 最大ドローダウンを小数点第二位まで四捨五入して返します。
// return math.Round(maxDrawdown) / 100
// }

// func MaxDrawdown(s *execute.SignalEvents, bars []Bar) float64 {
// var maxDrawdown float64 = 0.0
Expand Down
45 changes: 27 additions & 18 deletions pkg/analytics/profit_and_loss.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package analytics
import (
"math"
"time"

dbquery "v1/pkg/data/query"
"v1/pkg/execute"
"v1/pkg/trader"
)

// 課題 エグジットフラグメントを実装して、空売りにも対応するProfit関数を作ろう
Expand Down Expand Up @@ -35,7 +38,8 @@ import (
// return total
// }

func Profit(s *execute.SignalEvents) float64 {
// これは純利益を出力する関数
func Profi2(s *execute.SignalEvents) float64 {
if s == nil {
return 0.0
}
Expand Down Expand Up @@ -66,41 +70,29 @@ func Profit(s *execute.SignalEvents) float64 {
return profit
}

func Profi2(s *execute.SignalEvents) float64 {

func Profit(s *execute.SignalEvents) float64 {
if s == nil {
return 0.0
}
profit := 0.0
buyPrice := 0.0
beforeSell := 0.0
isHolding := false
var profit float64 = 0.0
var buyPrice float64

if s.Signals == nil || len(s.Signals) == 0 {
return 0.0
}
for i, signal := range s.Signals {
for _, signal := range s.Signals {

if i == 0 && signal.Side == "SELL" {
continue
}
if signal.Side != "BUY" && signal.Side != "SELL" {
return 0.0
}
if signal.Side == "BUY" {
buyPrice = signal.Price
isHolding = true
} else if signal.Side == "SELL" && buyPrice != 0.0 {
} else if signal.Side == "SELL" && buyPrice != 0 {
if signal.Price > buyPrice {
profit += (signal.Price - buyPrice) * signal.Size
isHolding = false
beforeSell = profit
}
buyPrice = 0 // Reset buy price after a sell
}
if isHolding {
return beforeSell
}
}

return profit
Expand Down Expand Up @@ -229,3 +221,20 @@ func MaxProfitTrade(s *execute.SignalEvents) (float64, time.Time) {
}
return maxProfitTrade, profitTime
}

func HoldingReturn(s *execute.SignalEvents) (float64, float64) {

acount := trader.NewAccount(initialBalance)

assetName := s.Signals[0].AssetName
duration := s.Signals[0].Duration
close, _ := dbquery.GetCloseData(assetName, duration)
size := acount.Balance

buyPrice := close[len(close)-1]

holdingReturn := (close[0] / buyPrice) * size
holdingReturnRatio := holdingReturn / size

return holdingReturn, holdingReturnRatio
}
30 changes: 30 additions & 0 deletions pkg/config/yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package config

import (
"os"

"gopkg.in/yaml.v3"
)

var data = "config.yml"

type Config struct {
AssetName string `yaml:"assetName"`
Dration string `yaml:"duration"`
}

func Yaml() (Config, error) {
t := Config{}

// Read the YAML file
file, errer := os.ReadFile(data)
if errer != nil {
return t, errer
}

err := yaml.Unmarshal([]byte(file), &t)
if err != nil {
return t, err
}
return t, nil
}
10 changes: 5 additions & 5 deletions pkg/data/query/get_pricedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func GetDateData(assetName string, duration string) ([]data.Date, error) {
return date, nil
}

func GetCloseData(assetName string, duration string) ([]data.Close, error) {
func GetCloseData(assetName string, duration string) ([]float64, error) {
db, err := sql.Open("sqlite3", "db/kline.db")
if err != nil {
log.Fatal(err)
Expand All @@ -209,10 +209,10 @@ func GetCloseData(assetName string, duration string) ([]data.Close, error) {
}
defer rows.Close()

var close []data.Close
var close []float64
for rows.Next() {
var k data.Close
err := rows.Scan(&k.Close)
var k float64
err := rows.Scan(&k)
if err != nil {
log.Fatal(err)
}
Expand All @@ -222,7 +222,7 @@ func GetCloseData(assetName string, duration string) ([]data.Close, error) {
if err := rows.Err(); err != nil {
log.Fatal(err)
}
fmt.Println(close)
// fmt.Println(close)
return close, nil
}

Expand Down
Loading

0 comments on commit 192e659

Please sign in to comment.