| [35bcb41] | 1 | package main
|
|---|
| 2 |
|
|---|
| 3 | import (
|
|---|
| 4 | "fmt"
|
|---|
| 5 | "strings"
|
|---|
| 6 | "time"
|
|---|
| 7 |
|
|---|
| 8 | "bp_project/server/db"
|
|---|
| 9 | )
|
|---|
| 10 |
|
|---|
| 11 | // promptPeriod reads a [from, to) date range for the P6 reports.
|
|---|
| 12 | func promptPeriod() (time.Time, time.Time, bool) {
|
|---|
| 13 | fromStr := prompt("From, inclusive (YYYY-MM-DD): ")
|
|---|
| 14 | toStr := prompt("To, exclusive (YYYY-MM-DD): ")
|
|---|
| 15 | from, err1 := time.Parse("2006-01-02", fromStr)
|
|---|
| 16 | to, err2 := time.Parse("2006-01-02", toStr)
|
|---|
| 17 | if err1 != nil || err2 != nil || !to.After(from) {
|
|---|
| 18 | fmt.Println("Invalid date range.")
|
|---|
| 19 | return time.Time{}, time.Time{}, false
|
|---|
| 20 | }
|
|---|
| 21 | return from, to, true
|
|---|
| 22 | }
|
|---|
| 23 |
|
|---|
| 24 | // ShowTopTraders - P6 report 1
|
|---|
| 25 | // Realized trading performance per user over a chosen period, via the
|
|---|
| 26 | // project.report_top_traders() SQL function (one query, bucketed by quarter
|
|---|
| 27 | // internally to measure consistency).
|
|---|
| 28 | func ShowTopTraders(s *Session) {
|
|---|
| 29 | fmt.Println("\n-- Top traders report --")
|
|---|
| 30 | from, to, ok := promptPeriod()
|
|---|
| 31 | if !ok {
|
|---|
| 32 | return
|
|---|
| 33 | }
|
|---|
| 34 |
|
|---|
| 35 | rows, err := db.DB.Query(`SELECT * FROM report_top_traders($1, $2)`, from, to)
|
|---|
| 36 | if err != nil {
|
|---|
| 37 | fmt.Println("Error:", err)
|
|---|
| 38 | return
|
|---|
| 39 | }
|
|---|
| 40 | defer rows.Close()
|
|---|
| 41 |
|
|---|
| 42 | header := fmt.Sprintf(" %-10s %14s %14s %10s %6s %6s %6s %10s",
|
|---|
| 43 | "Username", "Realized P/L", "Invested", "ROI %", "Prof.", "Loss", "Total", "Consist. %")
|
|---|
| 44 | fmt.Println()
|
|---|
| 45 | fmt.Println(header)
|
|---|
| 46 | fmt.Println(" " + strings.Repeat("-", len(header)-2))
|
|---|
| 47 |
|
|---|
| 48 | empty := true
|
|---|
| 49 | for rows.Next() {
|
|---|
| 50 | var username string
|
|---|
| 51 | var realizedPL, invested, roi, consistency float64
|
|---|
| 52 | var profitable, losing, total int64
|
|---|
| 53 | if err := rows.Scan(&username, &realizedPL, &invested, &roi, &profitable, &losing, &total, &consistency); err != nil {
|
|---|
| 54 | fmt.Println("scan error:", err)
|
|---|
| 55 | return
|
|---|
| 56 | }
|
|---|
| 57 | fmt.Printf(" %-10s %+14.4f %14.4f %10.2f %6d %6d %6d %10.2f\n",
|
|---|
| 58 | username, realizedPL, invested, roi, profitable, losing, total, consistency)
|
|---|
| 59 | empty = false
|
|---|
| 60 | }
|
|---|
| 61 | if empty {
|
|---|
| 62 | fmt.Println(" (no buy/sell/fee transactions in that range)")
|
|---|
| 63 | }
|
|---|
| 64 | }
|
|---|
| 65 |
|
|---|
| 66 | // ShowMarketPerformance - P6 report 2
|
|---|
| 67 | // Trading activity and price behaviour per market over a chosen period, via
|
|---|
| 68 | // the project.report_market_performance() SQL function.
|
|---|
| 69 | func ShowMarketPerformance(s *Session) {
|
|---|
| 70 | fmt.Println("\n-- Market performance report --")
|
|---|
| 71 | from, to, ok := promptPeriod()
|
|---|
| 72 | if !ok {
|
|---|
| 73 | return
|
|---|
| 74 | }
|
|---|
| 75 |
|
|---|
| 76 | rows, err := db.DB.Query(`SELECT * FROM report_market_performance($1, $2)`, from, to)
|
|---|
| 77 | if err != nil {
|
|---|
| 78 | fmt.Println("Error:", err)
|
|---|
| 79 | return
|
|---|
| 80 | }
|
|---|
| 81 | defer rows.Close()
|
|---|
| 82 |
|
|---|
| [9e6d8a2] | 83 | header := fmt.Sprintf(" %-6s %-5s %12s %8s %14s %12s %8s",
|
|---|
| 84 | "Symbol", "Quote", "Volume", "Trades", "Avg Price", "Return %", "Users")
|
|---|
| [35bcb41] | 85 | fmt.Println()
|
|---|
| 86 | fmt.Println(header)
|
|---|
| 87 | fmt.Println(" " + strings.Repeat("-", len(header)-2))
|
|---|
| 88 |
|
|---|
| 89 | empty := true
|
|---|
| 90 | for rows.Next() {
|
|---|
| 91 | var symbol, quote string
|
|---|
| [9e6d8a2] | 92 | var volume, avgPrice, returnPct float64
|
|---|
| [35bcb41] | 93 | var tradeCount, users int64
|
|---|
| [9e6d8a2] | 94 | if err := rows.Scan(&symbol, "e, &volume, &tradeCount, &avgPrice, &returnPct, &users); err != nil {
|
|---|
| [35bcb41] | 95 | fmt.Println("scan error:", err)
|
|---|
| 96 | return
|
|---|
| 97 | }
|
|---|
| [9e6d8a2] | 98 | fmt.Printf(" %-6s %-5s %12.4f %8d %14.6f %+12.2f %8d\n",
|
|---|
| 99 | symbol, quote, volume, tradeCount, avgPrice, returnPct, users)
|
|---|
| [35bcb41] | 100 | empty = false
|
|---|
| 101 | }
|
|---|
| 102 | if empty {
|
|---|
| 103 | fmt.Println(" (no market trades in that range)")
|
|---|
| 104 | }
|
|---|
| 105 | }
|
|---|