Init
This commit is contained in:
commit
67a5d3abc0
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017, Kevin Cotugno
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
83
cmd/interval/main.go
Normal file
83
cmd/interval/main.go
Normal file
@ -0,0 +1,83 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/shopspring/decimal"
|
||||
"encoding/csv"
|
||||
"log"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"strconv"
|
||||
|
||||
"tacitus/postgres"
|
||||
)
|
||||
|
||||
|
||||
func main() {
|
||||
client := postgres.NewClient()
|
||||
client.Name = "gdax"
|
||||
client.User = "gdax"
|
||||
|
||||
err := client.Open()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var start time.Time
|
||||
var end time.Time
|
||||
var done bool
|
||||
file, err := os.Create("btcusd_30_sec.csv")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
csv := csv.NewWriter(file)
|
||||
|
||||
first, _ := client.TradeService().Trade(1)
|
||||
|
||||
start = first.Timestamp.Truncate(30 * time.Second)
|
||||
end = start.Add(30 * time.Second)
|
||||
|
||||
err = csv.Write([]string{"timestamp", "price", "volume", "transactions"})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var lastPrice string
|
||||
for !done {
|
||||
trades, _ := client.TradeService().TradesInDateRange("BTCUSD", start, end)
|
||||
if len(trades) > 0 {
|
||||
var volume decimal.Decimal
|
||||
var transactions int
|
||||
|
||||
for _, t := range trades {
|
||||
volume = volume.Add(t.Size)
|
||||
transactions += 1
|
||||
lastPrice = t.Price.String()
|
||||
}
|
||||
|
||||
data := []string{end.String(), lastPrice, volume.String(), strconv.Itoa(transactions)}
|
||||
if err = csv.Write(data); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(end)
|
||||
} else {
|
||||
data := []string{end.String(), lastPrice, "0", "0"}
|
||||
if err = csv.Write(data); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
start = end
|
||||
end = end.Add(30 * time.Second)
|
||||
|
||||
if start.After(time.Date(2017, 8, 30, 16, 13, 50, 0, time.UTC)) {
|
||||
done = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
csv.Flush()
|
||||
file.Close()
|
||||
}
|
15
config/postgres.sql
Normal file
15
config/postgres.sql
Normal file
@ -0,0 +1,15 @@
|
||||
CREATE TABLE trades (
|
||||
id SERIAL PRIMARY KEY,
|
||||
trade_id integer NOT NULL,
|
||||
product CHAR(6) NOT NULL,
|
||||
price NUMERIC(1000, 8) NOT NULL,
|
||||
size NUMERIC(1000, 8) NOT NULL,
|
||||
buy BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
sell BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
timestamp TIMESTAMPTZ NOT NULL);
|
||||
|
||||
CREATE UNIQUE INDEX trade_id_product_INDEX ON trades (
|
||||
trade_id,
|
||||
product);
|
||||
|
||||
CREATE INDEX timestamp_index ON trades (timestamp);
|
53
postgres/client.go
Normal file
53
postgres/client.go
Normal file
@ -0,0 +1,53 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"text/template"
|
||||
|
||||
"tacitus"
|
||||
)
|
||||
|
||||
const connStr = `user={{.User}} dbname={{.Name}} sslmode={{.SslMode}}`
|
||||
|
||||
type Client struct {
|
||||
Name string
|
||||
User string
|
||||
SslMode string
|
||||
|
||||
tradeService TradeService
|
||||
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func NewClient() *Client {
|
||||
c := Client{}
|
||||
c.tradeService.client = &c
|
||||
c.SslMode = "disable"
|
||||
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c *Client) Open() error {
|
||||
buf := bytes.Buffer{}
|
||||
tmpl, _ := template.New("conn").Parse(connStr)
|
||||
tmpl.Execute(&buf, c)
|
||||
|
||||
db, err := sql.Open("postgres", buf.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = db.Ping(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.db = db
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) TradeService() tacitus.TradeService {
|
||||
return &c.tradeService
|
||||
}
|
96
postgres/trade_service.go
Normal file
96
postgres/trade_service.go
Normal file
@ -0,0 +1,96 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"tacitus"
|
||||
)
|
||||
|
||||
const (
|
||||
trade_insert = `INSERT INTO trades (trade_id, product, price, size, buy, ` +
|
||||
`sell, timestamp) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id;`
|
||||
trade_find = `SELECT id, trade_id, product, price, size, buy, sell, ` +
|
||||
`timestamp FROM trades WHERE id = $1;`
|
||||
trade_find_trade_id = `SELECT id, trade_id, product, price, size, buy, ` +
|
||||
`sell, timestamp FROM trades WHERE trade_id = $1 AND product = $2;`
|
||||
trade_delete = `DELETE FROM trades WHERE id = $1;`
|
||||
trades_in_date_range = `SELECT id, trade_id, product, price, size, buy, ` +
|
||||
`sell, timestamp FROM trades WHERE product = $1 AND timestamp >= $2 ` +
|
||||
`AND timestamp < $3;`
|
||||
)
|
||||
|
||||
type TradeService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (t *TradeService) Trade(id int) (*tacitus.Trade, error) {
|
||||
var tr tacitus.Trade
|
||||
|
||||
row := t.client.db.QueryRow(trade_find, id)
|
||||
if err := row.Scan(&tr.Id, &tr.TradeId, &tr.Product, &tr.Price, &tr.Size, &tr.Buy,
|
||||
&tr.Sell, &tr.Timestamp); err != nil {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tr, nil
|
||||
}
|
||||
|
||||
func (t *TradeService) TradeByTradeId(id int, prod string) (*tacitus.Trade, error) {
|
||||
var tr tacitus.Trade
|
||||
|
||||
row := t.client.db.QueryRow(trade_find_trade_id, id, prod)
|
||||
if err := row.Scan(&tr.Id, &tr.TradeId, &tr.Product, &tr.Price, &tr.Size, &tr.Buy,
|
||||
&tr.Sell, &tr.Timestamp); err != nil {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &tr, nil
|
||||
}
|
||||
|
||||
func (t *TradeService) CreateTrade(trade *tacitus.Trade) error {
|
||||
var id int
|
||||
res := t.client.db.QueryRow(trade_insert, trade.TradeId, trade.Product,
|
||||
trade.Price, trade.Size, trade.Buy, trade.Sell, trade.Timestamp)
|
||||
if err := res.Scan(&id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
trade.Id = id
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TradeService) DeleteTrade(id int) {
|
||||
t.client.db.Exec(trade_delete, id)
|
||||
}
|
||||
|
||||
func (t *TradeService) TradesInDateRange(product string, start,
|
||||
end time.Time) ([]tacitus.Trade, error) {
|
||||
|
||||
trades := make([]tacitus.Trade, 0)
|
||||
|
||||
rows, err := t.client.db.Query(trades_in_date_range, product, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var trade tacitus.Trade
|
||||
if err = rows.Scan(&trade.Id, &trade.TradeId, &trade.Product, &trade.Price,
|
||||
&trade.Size, &trade.Buy, &trade.Sell, &trade.Timestamp); err != nil {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trades = append(trades, trade)
|
||||
}
|
||||
|
||||
if rows.Err() != nil {
|
||||
return nil, rows.Err()
|
||||
}
|
||||
|
||||
return trades, nil
|
||||
}
|
26
trade.go
Normal file
26
trade.go
Normal file
@ -0,0 +1,26 @@
|
||||
package tacitus
|
||||
|
||||
import (
|
||||
"github.com/shopspring/decimal"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type Trade struct {
|
||||
Id int
|
||||
TradeId int
|
||||
Product string
|
||||
Price decimal.Decimal
|
||||
Size decimal.Decimal
|
||||
Buy bool
|
||||
Sell bool
|
||||
Timestamp time.Time
|
||||
}
|
||||
|
||||
type TradeService interface {
|
||||
Trade(id int) (*Trade, error)
|
||||
TradeByTradeId(id int, prod string) (*Trade, error)
|
||||
CreateTrade(t *Trade) error
|
||||
DeleteTrade(id int)
|
||||
TradesInDateRange(product string, start, end time.Time) ([]Trade, error)
|
||||
}
|
Reference in New Issue
Block a user