Skip to content

Commit

Permalink
Initial
Browse files Browse the repository at this point in the history
  • Loading branch information
SlashGordon committed Aug 27, 2021
1 parent 57566b4 commit 80dcee9
Show file tree
Hide file tree
Showing 15 changed files with 1,280 additions and 0 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
on: [push, pull_request]
name: CI
jobs:
test:
strategy:
matrix:
go-version: [1.13.x, 1.14.x, 1.15.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
- name: Test
run: go test -race -covermode atomic -coverprofile profile.cov ./...
- name: Send coverage
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
flag-name: Go-${{ matrix.go-version }}
parallel: true
finish:
needs: test
runs-on: ubuntu-latest
steps:
- uses: shogo82148/actions-goveralls@v1
with:
parallel-finished: true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@

# Dependency directories (remove the comment below to include it)
# vendor/
.vscode/*
.gotrader.yaml
data_dir/*
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
[![CI](https://github.com/SlashGordon/gotrader/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/SlashGordon/gotrader/actions/workflows/ci.yaml)
[![Coverage Status](https://coveralls.io/repos/github/SlashGordon/gotrader/badge.svg?branch=master)](https://coveralls.io/github/SlashGordon/gotrader?branch=master)
# gotrader
Alpaca trader

## config

Add a file named `.gotrader.yaml` to your workspace with the following content:

```yaml
APCA_API_KEY_ID: "alpacaid"
APCA_API_SECRET_KEY: "alpacakey"
APCA_API: "https://paper-api.alpaca.markets"
`````
34 changes: 34 additions & 0 deletions backtest/backtest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package backtest

import (
"github.com/dirkolbrich/gobacktest"
"github.com/dirkolbrich/gobacktest/data"
"github.com/dirkolbrich/gobacktest/strategy"
)

func Run(symbols []string, dataDir string) {
// initiate a new backtester
test := gobacktest.New()

test.SetSymbols(symbols)

// create a data provider and load the data into the backtest
data := &data.BarEventFromCSVFile{FileDir: dataDir}
data.Load(symbols)
test.SetData(data)

// choose a strategy
strategy := strategy.BuyAndHold()

// create an asset and append it to the strategy
strategy.SetChildren(gobacktest.NewAsset("SHOP"))

// load the strategy into the backtest
test.SetStrategy(strategy)

// run the backtest
test.Run()

// print the results of the test
test.Stats().PrintResult()
}
34 changes: 34 additions & 0 deletions cmd/backtest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cmd

import (
"github.com/SlashGordon/gotrader/backtest"
"github.com/spf13/cobra"
)

func init() {

var (
strategyName string
symbols []string
dataDir string
days int
portfolioCash float64
)

startCmd := &cobra.Command{
Use: "backtest",
Short: "Start backtest for given strategy",
Run: func(cmd *cobra.Command, args []string) {
backtest.Run(symbols, dataDir)
},
}
configFlag := startCmd.PersistentFlags()
configFlag.StringVarP(&strategyName, "strategy", "s", "", "name of strategy")
configFlag.StringVarP(&dataDir, "data", "d", "data", "data dir")
configFlag.IntVarP(&days, "days", "l", 300, "lookback in days. If lookback is set to 300 the backtest runs from now -300 until now.")
configFlag.Float64VarP(&portfolioCash, "portfolioCash", "c", 1000.0, "Initial cash of the porfolio.")
configFlag.StringSliceVarP(&symbols, "symbols", "y", nil, "list of symbols")
cobra.MarkFlagRequired(configFlag, "config")

RootCmd.AddCommand(startCmd)
}
70 changes: 70 additions & 0 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package cmd

import (
"fmt"
"log"
"os"

"github.com/SlashGordon/gotrader/utils"
"github.com/alpacahq/alpaca-trade-api-go/alpaca"
"github.com/alpacahq/alpaca-trade-api-go/common"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var cfgFile string

// RootCmd global entry point
var RootCmd = &cobra.Command{
Use: "gotrader",
}

// Execute ...
func Execute() {

if err := RootCmd.Execute(); err != nil {
log.Fatal(err)
os.Exit(1)
}
}

func init() {
cobra.OnInitialize(initConfig)
RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.gotrader.yaml)")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}

// Search config in home directory with name ".cobra-example" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".gotrader")
}

viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
utils.Logger.Info("Using config file:", viper.ConfigFileUsed())
// Check for environment variables
if common.Credentials().ID == "" {
os.Setenv(common.EnvApiKeyID, viper.GetString(common.EnvApiKeyID))
}
if common.Credentials().Secret == "" {
os.Setenv(common.EnvApiSecretKey, viper.GetString(common.EnvApiSecretKey))
}
alpaca.SetBaseUrl(viper.GetString("APCA_API"))
utils.Logger.Infof("Running w/ credentials [%v %v]\n", common.Credentials().ID, common.Credentials().Secret)
}
}
37 changes: 37 additions & 0 deletions cmd/dump.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmd

import (
"github.com/SlashGordon/gotrader/trader"
"github.com/SlashGordon/gotrader/utils"
"github.com/spf13/cobra"
)

func init() {

var (
symbols []string
dataDir string
days int
)

startCmd := &cobra.Command{
Use: "dump",
Short: "downloads price infos for given stocks",
Run: func(cmd *cobra.Command, args []string) {
client := trader.NewTrader()
for _, sym := range symbols {
utils.Logger.Info("Dump data for " + sym)
if err := client.WriteBarToCSV(sym, days, dataDir); err != nil {
utils.Logger.Error(err)
}
}
},
}
configFlag := startCmd.PersistentFlags()
configFlag.StringSliceVarP(&symbols, "symbols", "s", nil, "list of symbols")
configFlag.StringVarP(&dataDir, "data", "d", "data", "data dir")
configFlag.IntVarP(&days, "days", "l", 300, "Set history data size")
cobra.MarkFlagRequired(configFlag, "config")

RootCmd.AddCommand(startCmd)
}
17 changes: 17 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module github.com/SlashGordon/gotrader

go 1.15

require (
github.com/alpacahq/alpaca-trade-api-go v1.8.2
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be
github.com/dirkolbrich/gobacktest v0.3.0
github.com/iamjinlei/go-tart v0.0.0-20210623083942-ceb57e98706b
github.com/mchirico/date v0.0.2
github.com/mitchellh/go-homedir v1.1.0
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.2.1
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.7.0
gonum.org/v1/gonum v0.9.3 // indirect
)
Loading

0 comments on commit 80dcee9

Please sign in to comment.