diff --git a/cmd/mop/main.go b/cmd/mop/main.go index fbf58cd..f304265 100644 --- a/cmd/mop/main.go +++ b/cmd/mop/main.go @@ -55,54 +55,96 @@ Enter comma-delimited list of stock tickers when prompted. Press any key to continue ` -func getuserinput() string{ + + +func getuserinput(preset *Preset, sc mop.Stock) string{ scanner := bufio.NewScanner(os.Stdin) + var precondition string + var instrumentname string + var buyorsell string - // Prompt the user to enter the first date - fmt.Print("Enter Command: ") - scanner.Scan() - cmdstr := scanner.Text() - preset := Preset{} - inputcmd := strings.Split(cmdstr, " ") - if len(inputcmd) == 2 { - if inputcmd[0] == "buy" { - preset.Direction = 23 - }else if inputcmd[0] == "sell" { - preset.Direction = 24 + if sc.Ticker == "" { + fmt.Print("Enter Command: ") + scanner.Scan() + cmdstr := scanner.Text() + + inputcmd := strings.Split(cmdstr, " ") + if len(inputcmd) == 2 { + if inputcmd[0] == "buy" { + preset.Direction = 23 + }else if inputcmd[0] == "sell" { + preset.Direction = 24 + }else{ + return "" + } }else{ return "" } + preset.Scode = inputcmd[1] + }else{ + preset.Direction = 23 + preset.Scode = sc.Dividend[2:] + f1, _ := strconv.ParseFloat(sc.LastTrade, 64) + f2, _ := strconv.ParseFloat(sc.Change, 64) + precondition = fmt.Sprintf("%s>%.2f", sc.LastTrade, f1-f2) + instrumentname = sc.Ticker[2:] + } - fmt.Print("Enter Condition: ") - scanner.Scan() - condition := scanner.Text() - if strings.Contains(condition, ">") { - preset.Ifbelow = 0 - preset.Ifabove, _ = strconv.ParseFloat(strings.Replace(condition, ">", "", -1), 64) - }else if strings.Contains(condition, "<") { - preset.Ifabove = 0 - preset.Ifbelow, _ = strconv.ParseFloat(strings.Replace(condition, "<", "", -1), 64) - } - - fmt.Print("Enter Vol: ") - scanner.Scan() - vol := scanner.Text() - preset.Vol, _ = strconv.ParseFloat(vol, 64) + if preset.Direction == 23 { + buyorsell = "buy" + } else { + buyorsell = "sell" + } - //fmt.Print(preset) - jsonData, err := json.Marshal(preset) - if err != nil { - fmt.Println(err) - } - extraField := `,"cmd": "preset"}` - jsonData = append(jsonData[:len(jsonData)-1], extraField...) - message := string(jsonData) - fmt.Println(message) + if preset.Ifbelow == 0 && preset.Ifabove == 0 { + + }else if preset.Ifbelow == 0 { + precondition = fmt.Sprintf(">%f", preset.Ifabove) + }else{ + precondition = fmt.Sprintf("<%f", preset.Ifbelow) + } - return message + fmt.Printf("Enter Condition[%s %s][%s]: ", buyorsell, preset.Scode+instrumentname, precondition) + + scanner.Scan() + condition := scanner.Text() + if strings.Contains(condition, ">") { + preset.Ifbelow = 0 + preset.Ifabove, _ = strconv.ParseFloat(strings.Replace(condition, ">", "", -1), 64) + }else if strings.Contains(condition, "<") { + preset.Ifabove = 0 + preset.Ifbelow, _ = strconv.ParseFloat(strings.Replace(condition, "<", "", -1), 64) + }else{ + return "" + } + + if preset.Ifbelow == 0 && preset.Ifabove == 0 { + precondition = "" + }else if preset.Ifbelow == 0 { + precondition = fmt.Sprintf(">%.2f", preset.Ifabove) + }else{ + precondition = fmt.Sprintf("<%.2f", preset.Ifbelow) } - return "" + fmt.Printf("Enter Vol[%s %s][%s]: ", buyorsell, preset.Scode+instrumentname, precondition) + scanner.Scan() + vol := scanner.Text() + preset.Vol, _ = strconv.ParseFloat(vol, 64) + if preset.Vol == 0 { + return "" + } + + //fmt.Print(preset) + jsonData, err := json.Marshal(preset) + if err != nil { + fmt.Println(err) + } + extraField := `,"cmd": "preset"}` + jsonData = append(jsonData[:len(jsonData)-1], extraField...) + message := string(jsonData) + fmt.Println(message) + + return message } //----------------------------------------------------------------------------- @@ -123,6 +165,8 @@ func mainLoop(screen *mop.Screen, profile *mop.Profile, mode string) { upDownJump := profile.UpDownJump redrawQuotesFlag := false redrawMarketFlag := false + account := "" + var canstock mop.Stock // 创建一个用于存储用户输入的缓冲区 input := "" @@ -145,6 +189,12 @@ func mainLoop(screen *mop.Screen, profile *mop.Profile, mode string) { // create a new MQTT client opts := mqtt.NewClientOptions() opts.AddBroker("tcp://119.29.166.226:1883") + currentTime := time.Now().UnixNano() / int64(time.Millisecond) + millisecondsString := strconv.FormatInt(currentTime, 10) + opts.SetClientID("client-mop-"+millisecondsString) + opts.SetUsername("sandy") + opts.SetPassword("Abb123456.") + client := mqtt.NewClient(opts) // connect to the MQTT broker @@ -230,11 +280,23 @@ loop: redrawQuotesFlag = true } else if event.Key == termbox.KeyArrowUp || event.Ch == 'k' { screen.DecreaseOffset(1) - screen.Selectmoveup() + screen.Selectmoveup(quotes) + selstock := quotes.Getselectedinfo(screen.Selectindex()) + if selstock != nil { + canstock = *selstock + }else{ + canstock = mop.Stock{} + } redrawQuotesFlag = true } else if event.Key == termbox.KeyArrowDown || event.Ch == 'j' { screen.IncreaseOffset(1) screen.Selectmovedown(quotes) + selstock := quotes.Getselectedinfo(screen.Selectindex()) + if selstock != nil { + canstock = *selstock + }else{ + canstock = mop.Stock{} + } redrawQuotesFlag = true } else if event.Key == termbox.KeyHome { screen.ScrollTop() @@ -242,6 +304,18 @@ loop: } else if event.Key == termbox.KeyEnd { screen.ScrollBottom() redrawQuotesFlag = true + } else if event.Ch == 'b' { + data := map[string]string{ + "cmd": "getaccount", + } + jsonData, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + } + message := string(jsonData) + token := client.Publish("stock/request/470100037961", 0, false, message) + token.Wait() + account = "470100037961" } else if event.Key == termbox.KeySpace { data := map[string]string{ "cmd": "getaccount", @@ -251,21 +325,24 @@ loop: fmt.Println(err) } message := string(jsonData) - token := client.Publish("stock/request", 0, false, message) + token := client.Publish("stock/request/620000301588", 0, false, message) token.Wait() + account = "620000301588" } else if event.Ch >= '0' && event.Ch <= '9' { input += string(event.Ch) } else if event.Key == termbox.KeyEnter { indexnum, err := strconv.Atoi(input) selectindex := screen.Selectindex() if selectindex > 0 { - indexnum = selectindex - err = nil - } + selcode := canstock.Dividend + quotes.Sendstockgraphreq(selcode, false) + quotes.Sendstockgraphreq(selcode, true) + }else{ //fmt.Println("indexnum:", indexnum) - if err == nil && indexnum > 0 { - quotes.Sendstockgraphreq(indexnum, false) - quotes.Sendstockgraphreq(indexnum, true) + if err == nil && indexnum > 0 { + quotes.Sendstockgraphreq(indexnum, false) + quotes.Sendstockgraphreq(indexnum, true) + } } // 清空输入缓冲区 input = "" @@ -356,19 +433,21 @@ loop: }else if strings.HasPrefix(msg.Topic(), "stock/image/time"){ os.Stdout.Write(msg.Payload()) - jsonstr := getuserinput() + preset := &Preset{} + jsonstr := getuserinput(preset, canstock) if jsonstr != "" { - token := client.Publish("stock/request", 0, false, jsonstr) + token := client.Publish("stock/request/"+account, 0, false, jsonstr) token.Wait() } } }else if strings.HasPrefix(msg.Topic(), "stock/response"){ fmt.Print("\033[2J") showposition(string(msg.Payload()) ,si) - - jsonstr := getuserinput() + + preset := &Preset{} + jsonstr := getuserinput(preset, canstock) if jsonstr != "" { - token := client.Publish("stock/request", 0, false, jsonstr) + token := client.Publish("stock/request/"+account, 0, false, jsonstr) token.Wait() } } @@ -412,6 +491,10 @@ type Positions struct { Latestinfo string `json:"lastinfo"` } +func float2Str(f float64) string { + return fmt.Sprintf("%.2f", f) +} + func showposition(payload string,si map[string]*stock.Stock) string{ var positions Positions @@ -422,10 +505,14 @@ func showposition(payload string,si map[string]*stock.Stock) string{ } var data [][]string + var totalFloatProfit float64 = 0.0 + var totalMarketValue float64 = 0.0 //fmt.Println(positions.Position) for _, pos := range positions.Position { row := []string{pos.Scode + " " +pos.Sname, fmt.Sprintf("%.2f", pos.Openprice), fmt.Sprintf("%.2f", pos.Floatprofit), fmt.Sprintf("%.2f", pos.Marketvalue)} data = append(data, row) + totalFloatProfit += pos.Floatprofit + totalMarketValue += pos.Marketvalue } for _, pos := range positions.Preset { @@ -455,8 +542,8 @@ func showposition(payload string,si map[string]*stock.Stock) string{ tableString := &strings.Builder{} table := tablewriter.NewWriter(tableString) - table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) - table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer + table.SetHeader([]string{"Instrument", "Avg. Price", "Float Profit", "Market Value"}) + table.SetFooter([]string{"", "Total", float2Str(totalFloatProfit), float2Str(totalMarketValue)}) // Add Footer //table.EnableBorder(false) // Set Border to false table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, diff --git a/day.go b/day.go new file mode 100644 index 0000000..d15776d --- /dev/null +++ b/day.go @@ -0,0 +1,297 @@ +package mop + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strconv" + "strings" + "time" + + //"github.com/markcheno/go-talib" +) + +type KLineData struct { + Day string `json:"day"` + Open float64 `json:"open,string"` + High float64 `json:"high,string"` + Low float64 `json:"low,string"` + Close float64 `json:"close,string"` + Volume float64 `json:"volume,string"` +} + +func getURL(code string, ts int, count int) string { + return fmt.Sprintf("http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=%s&scale=%d&ma=5&datalen=%d", code, ts, count) +} + +func getKLineData(url string) ([]KLineData, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var data []KLineData + err = json.Unmarshal(body, &data) + if err != nil { + return nil, err + } + + return data, nil +} +func get_price_sina(code string, end_date string, count int, frequency string, startdate string) ([]KLineData, error) { + frequency = strings.Replace(frequency, "1d", "240m", 1) + frequency = strings.Replace(frequency, "1w", "1200m", 1) + frequency = strings.Replace(frequency, "1M", "7200m", 1) + + ts, err := strconv.Atoi(strings.TrimSuffix(frequency, "m")) + if err != nil { + return nil, err + } + + if end_date != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { + endDate, err := time.Parse("2006-01-02", end_date) + if err != nil { + return nil, err + } + + unit := 1 + if frequency == "1200m" { + unit = 4 + } else if frequency == "7200m" { + unit = 29 + } + + days := int(time.Since(endDate).Hours() / 24) + count = count + days/unit + } + + url := getURL(code, ts, count) + //fmt.Printf("url: %s\n", url) + data, err := getKLineData(url) + if err != nil { + return nil, err + } + //fmt.Printf("data: %v\n", data) + if startdate != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { + endDate := time.Now() + //endDate, err := time.Parse("2006-01-02", end_date) + //if err != nil { + // return nil, err + //} + + start_date, err := time.Parse("2006-01-02", startdate) + if err != nil { + return nil, err + } + + filteredData := []KLineData{} + for _, d := range data { + day, err := time.Parse("2006-01-02", d.Day) + if err != nil { + return nil, err + } + + if day.After(start_date) && (day.Before(endDate) || day.Equal(endDate)) { + filteredData = append(filteredData, d) + } + } + + return filteredData, nil + } + + return data, nil +} + +func findMaxHighAndMinLow(data []KLineData) (float64, float64) { + maxHigh := data[0].High + minLow := data[0].Low + + for _, d := range data { + if d.High > maxHigh { + maxHigh = d.High + } + if d.Low < minLow { + minLow = d.Low + } + } + + return maxHigh, minLow +} + +// 将interface{}类型转换为float64类型 +func convertToFloat64(value interface{}) float64 { + if floatValue, ok := value.(float64); ok { + return floatValue + } + if stringValue, ok := value.(string); ok { + floatValue, err := strconv.ParseFloat(stringValue, 64) + if err == nil { + return floatValue + } + } + return 0 +} + +func getURLTencent(code string, start string, count int) string { + // 给定的日期 + datestr := "" + date, err := time.Parse("2006-01-02", start) + if err != nil { + fmt.Println("解析日期失败:", err) + }else{ + futureDate := date.AddDate(0, 0, 10) + if futureDate.Before(time.Now()){ + datestr = futureDate.Format("2006-01-02") + fmt.Println(datestr) + } + } + + return fmt.Sprintf("https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?param=%s,day,,%s,%d,qfq", code, datestr, count) +} + +func getKLineTencent(url string, code string)([]KLineData, error){ + resp, err := http.Get(url) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + var dataMap map[string]interface{} + err = json.Unmarshal(body, &dataMap) + if err != nil { + fmt.Println("解析JSON字符串失败", err) + return nil, err + } + klineData := make([]KLineData, 0) + // 获取K线数据 + if shData, ok := dataMap["data"].(map[string]interface{})[code].(map[string]interface{}); ok { + if qfqday, ok := shData["qfqday"].([]interface{}); ok { + + for _, item := range qfqday { + if data, ok := item.([]interface{}); ok { + klineData = append(klineData, KLineData{ + Day: data[0].(string), + Open: convertToFloat64(data[1]), + High: convertToFloat64(data[3]), + Low: convertToFloat64(data[4]), + Close: convertToFloat64(data[2]), + Volume: convertToFloat64(data[5]), + }) + } + } + //fmt.Println(klineData) + return klineData,nil + }else if day, ok := shData["day"].([]interface{}); ok { + for _, item := range day { + if data, ok := item.([]interface{}); ok { + klineData = append(klineData, KLineData{ + Day: data[0].(string), + Open: convertToFloat64(data[1]), + High: convertToFloat64(data[3]), + Low: convertToFloat64(data[4]), + Close: convertToFloat64(data[2]), + Volume: convertToFloat64(data[5]), + }) + } + } + return klineData,nil + } + } + return klineData,nil +} + +func get_price_tencent(code string, end_date string, count int, frequency string, startdate string) ([]KLineData, error) { + frequency = strings.Replace(frequency, "1d", "240m", 1) + frequency = strings.Replace(frequency, "1w", "1200m", 1) + frequency = strings.Replace(frequency, "1M", "7200m", 1) + + if end_date != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { + endDate, err := time.Parse("2006-01-02", end_date) + if err != nil { + return nil, err + } + + unit := 1 + if frequency == "1200m" { + unit = 4 + } else if frequency == "7200m" { + unit = 29 + } + + days := int(time.Since(endDate).Hours() / 24) + count = count + days/unit + } + /* + url := getURL(code, ts, count) + fmt.Printf("url: %s\n", url) + data, err := getKLineData(url) + */ + url := getURLTencent(code, startdate, 10) + //fmt.Printf("url: %s\n", url) + data, err := getKLineTencent(url, code) + if err != nil { + return nil, err + } + //fmt.Printf("data: %v\n", data) + if startdate != "" && (frequency == "240m" || frequency == "1200m" || frequency == "7200m") { + endDate := time.Now() + //endDate, err := time.Parse("2006-01-02", end_date) + //if err != nil { + // return nil, err + //} + start_date, err := time.Parse("2006-01-02", startdate) + if err != nil { + return nil, err + } + + filteredData := []KLineData{} + for _, d := range data { + day, err := time.Parse("2006-01-02", d.Day) + if err != nil { + return nil, err + } + //fmt.Println(start_date, endDate, day) + if day.After(start_date) && (day.Before(endDate) || day.Equal(endDate)) { + filteredData = append(filteredData, d) + } + } + + return filteredData, nil + } + + return data, nil +} + +func getnextdaysHL(code string, start_date string) (float64, float64, float64, float64 ,int) { + //data, err := get_price_sina(code, "", 30, "240m", start_date) + data, err := get_price_tencent(code, "", 30, "240m", start_date) + if err != nil { + return 0, 0, 0, 0, 0 + } + + pre := 3 + if len(data) < 3 { + pre = len(data) + } + + //fmt.Printf("data: %v\n", data[:3]) + caldata := data[:pre] + maxHigh, minLow := findMaxHighAndMinLow(caldata) + //fmt.Println(maxHigh, minLow) + + return caldata[0].Open, caldata[pre-1].Close, maxHigh, minLow, pre +} + + diff --git a/line_editor.go b/line_editor.go index 1d6d3f6..de9c269 100644 --- a/line_editor.go +++ b/line_editor.go @@ -64,6 +64,30 @@ func (editor *LineEditor) Prompt(command rune) *LineEditor { return editor } +func (editor *LineEditor) PromptInstrumet(command rune) *LineEditor { + filterPrompt := `Set filter: ` + + if filter := editor.quotes.profile.Filter; len(filter) > 0 { + filterPrompt = `Set filter (` + filter + `): ` + } + + prompts := map[rune]string{ + '+': `Add tickers: `, '-': `Remove tickers: `, + 'f': filterPrompt, + } + if prompt, ok := prompts[command]; ok { + editor.prompt = prompt + editor.command = command + + editor.screen.DrawLine(0, 3, ``+editor.prompt+``) + termbox.SetCursor(len(editor.prompt), 3) + termbox.Flush() + + } + + return editor +} + func (editor *LineEditor) insertString(str string) { for _, ch := range str { editor.insertCharacter(ch) diff --git a/screen.go b/screen.go index 9e08d8d..0561432 100644 --- a/screen.go +++ b/screen.go @@ -117,22 +117,32 @@ func (screen *Screen) DecreaseOffset(n int) { } } -func (screen *Screen) Selectmoveup() { +func (screen *Screen) Selectmoveup(quotes *Quotes) { if screen.selectindex >= 5 { screen.selectindex -= 1 } + if screen.selectindex == 4 { + screen.DrawLine(0, 3, ``+" "+``) + }else{ + screen.DrawLine(0, 3, ``+quotes.stocks[screen.selectindex-5].Ticker+``) + } } func (screen *Screen) Selectmovedown(quotes *Quotes) { if screen.selectindex < len(quotes.stocks) + 4 { screen.selectindex += 1 } + screen.DrawLine(0, 3, ``+quotes.stocks[screen.selectindex-5].Ticker+``) } func (screen *Screen) Selectindex() int { return screen.selectindex - 4 } +func (screen *Screen) Selectpreset() int { + return screen.selectindex - 4 +} + func (screen *Screen) ScrollTop() { screen.offset = 0 } diff --git a/yahoo_crumb.go b/yahoo_crumb.go new file mode 100644 index 0000000..fc8a9c4 --- /dev/null +++ b/yahoo_crumb.go @@ -0,0 +1,102 @@ +// Copyright (c) 2013-2023 by Michael Dvorkin and contributors. All Rights Reserved. +// Use of this source code is governed by a MIT-style license that can +// be found in the LICENSE file. + +package mop + +import ( + "io/ioutil" + "net/http" + "strings" + "net/url" +) + +const crumbURL = "https://query1.finance.yahoo.com/v1/test/getcrumb" +const cookieURL = "https://login.yahoo.com" +const userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/113.0" + +func fetchCrumb(cookies string) string { + proxyUrl, err := url.Parse("http://172.29.100.107:28888") + if err != nil { + panic(err) + } + + transport := &http.Transport{ + Proxy: http.ProxyURL(proxyUrl), + } + + client := &http.Client{ + Transport: transport, + } + //client := http.Client{} + request, err := http.NewRequest("GET", crumbURL, nil) + if err != nil { + panic(err) + } + + request.Header = http.Header{ + "Accept": {"*/*"}, + "Accept-Encoding": {"gzip, deflate, br"}, + "Accept-Language": {"en-US,en;q=0.5"}, + "Connection": {"keep-alive"}, + "Content-Type": {"text/plain"}, + "Cookie": {cookies}, + "Host": {"query1.finance.yahoo.com"}, + "Sec-Fetch-Dest": {"empty"}, + "Sec-Fetch-Mode": {"cors"}, + "Sec-Fetch-Site": {"same-site"}, + "TE": {"trailers"}, + "User-Agent": {userAgent}, + } + + response, err := client.Do(request) + if err != nil { + panic(err) + } + defer response.Body.Close() + + body, err := ioutil.ReadAll(response.Body) + if err != nil { + panic(err) + } + + return string(body[:]) +} + +func fetchCookies() string { + client := http.Client{} + request, err := http.NewRequest("GET", cookieURL, nil) + if err != nil { + panic(err) + } + + request.Header = http.Header{ + "Accept": {"*/*"}, + "Accept-Encoding": {"gzip, deflate, br"}, + "Accept-Language": {"en-US,en;q=0.5"}, + "Connection": {"keep-alive"}, + "Host": {"login.yahoo.com"}, + "Sec-Fetch-Dest": {"document"}, + "Sec-Fetch-Mode": {"navigate"}, + "Sec-Fetch-Site": {"none"}, + "Sec-Fetch-User": {"?1"}, + "TE": {"trailers"}, + "Update-Insecure-Requests": {"1"}, + "User-Agent": {userAgent}, + } + + response, err := client.Do(request) + if err != nil { + panic(err) + } + defer response.Body.Close() + + var result string + for _, cookie := range response.Cookies() { + if cookie.Name != "AS" { + result += cookie.Name + "=" + cookie.Value + "; " + } + } + result = strings.TrimSuffix(result, "; ") + return result +} diff --git a/yahoo_market.go b/yahoo_market.go index 1584124..753405f 100644 --- a/yahoo_market.go +++ b/yahoo_market.go @@ -5,16 +5,16 @@ package mop import ( + "encoding/json" "fmt" "io/ioutil" "net/http" - "encoding/json" - //"net/url" + "net/url" "easyquotation/stock" ) -const marketURL = `https://query1.finance.yahoo.com/v6/finance/quote?symbols=%s` +const marketURL = `https://query1.finance.yahoo.com/v7/finance/quote?crumb=%s&symbols=%s` const marketURLQueryParts = `&range=1d&interval=5m&indicators=close&includeTimestamps=false&includePrePost=false&corsDomain=finance.yahoo.com&.tsrc=finance` // Market stores current market information displayed in the top three lines of @@ -38,6 +38,8 @@ type Market struct { res map[string]*stock.Stock watchlist *Watchlist + cookies string // cookies for auth + crumb string // crumb for the cookies, to be applied as a query param } // Returns new initialized Market struct. @@ -59,7 +61,9 @@ func NewMarket(res map[string]*stock.Stock, watchlist *Watchlist) *Market { market.Euro = make(map[string]string) market.Gold = make(map[string]string) - market.url = fmt.Sprintf(marketURL, `^DJI,^IXIC,^GSPC,^N225,^HSI,^FTSE,^GDAXI,^TNX,CL=F,CNH=X,EUR=X,GC=F`) + marketURLQueryParts + market.cookies = fetchCookies() + market.crumb = fetchCrumb(market.cookies) + market.url = fmt.Sprintf(marketURL, market.crumb, `^DJI,^IXIC,^GSPC,^N225,^HSI,^FTSE,^GDAXI,^TNX,CL=F,CNH=X,EUR=X,GC=F`) + marketURLQueryParts market.errors = `` market.res = res @@ -78,6 +82,7 @@ func (market *Market) Fetch() (self *Market) { market.errors = "" } }() + /* // Define the proxy URL //proxyUrl, err := url.Parse("http://172.29.100.107:28888") //if err != nil { @@ -98,12 +103,55 @@ func (market *Market) Fetch() (self *Market) { panic(err) } + defer response.Body.Close() + body, err := ioutil.ReadAll(response.Body) + if err != nil { + panic(err) + }*/ + proxyUrl, err := url.Parse("http://172.29.100.107:28888") + if err != nil { + panic(err) + } + + transport := &http.Transport{ + Proxy: http.ProxyURL(proxyUrl), + } + + client := &http.Client{ + Transport: transport, + } + //client := http.Client{} + request, err := http.NewRequest("GET", market.url, nil) + if err != nil { + panic(err) + } + + request.Header = http.Header{ + "Accept": {"*/*"}, + "Accept-Language": {"en-US,en;q=0.5"}, + "Connection": {"keep-alive"}, + "Content-Type": {"application/json"}, + "Cookie": {market.cookies}, + "Host": {"query1.finance.yahoo.com"}, + "Origin": {"https://finance.yahoo.com"}, + "Referer": {"https://finance.yahoo.com"}, + "Sec-Fetch-Dest": {"empty"}, + "Sec-Fetch-Mode": {"cors"}, + "Sec-Fetch-Site": {"same-site"}, + "TE": {"trailers"}, + "User-Agent": {userAgent}, + } + + response, err := client.Do(request) + if err != nil { + panic(err) + } + defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { panic(err) } - //fmt.Println(string(body)) body = market.isMarketOpen(body) return market.extract(body) } diff --git a/yahoo_quotes.go b/yahoo_quotes.go index 1913fee..07fba90 100644 --- a/yahoo_quotes.go +++ b/yahoo_quotes.go @@ -204,9 +204,10 @@ func (quotes *Quotes) Fetch() (self *Quotes) { //write a function to save the slice of quotes.stocks to file func (quotes *Quotes) SaveStocks() { - //fmt.Println("save") - //fmt.Println(quotes.stocks) - //fmt.Println(quotes.profile.mode) + if quotes.profile.mode == "review"{ + return + } + filedata, err := json.MarshalIndent(quotes.totalstocks, "", " ") if err != nil { fmt.Println(err) @@ -383,18 +384,27 @@ func padString(str string, length int) string { return str } -func (quotes *Quotes) Sendstockgraphreq(index int, istime bool) { - if index > len(quotes.totalstocks){ - return +func (quotes *Quotes) Sendstockgraphreq(index interface{}, istime bool) { + var selcode string + if intvalue, ok := index.(int); ok { + if intvalue > len(quotes.totalstocks){ + return + } + selcode = quotes.totalstocks[intvalue-1].Scode + } + + if stringValue, ok := index.(string); ok { + selcode = stringValue } + topic := "my/topic" - itemsel := quotes.getitembyscode(quotes.totalstocks[index-1].Scode) + itemsel := quotes.getitembyscode(selcode) data := map[string]interface{}{ - "scode": quotes.totalstocks[index-1].Scode, + "scode": selcode,//quotes.totalstocks[index-1].Scode, "tier": 0, "daysback": itemsel.Daysback, "stdprice": itemsel.Enterprice, - "name": strings.TrimSpace(quotes.totalstocks[index-1].Sname), + "name": quotes.res[selcode].Base.Name, //strings.TrimSpace(quotes.totalstocks[index-1].Sname), "ed": itemsel.AnalyseDay, } if istime { @@ -410,6 +420,13 @@ func (quotes *Quotes) Sendstockgraphreq(index int, istime bool) { token.Wait() } +func (quotes *Quotes) Getselectedinfo(index int) *Stock { + if index > len(quotes.totalstocks) || index < 1 { + return nil + } + return "es.stocks[index-1] +} + func (quotes *Quotes) parsereview(res map[string]*stock.Stock) (*Quotes, error) { var scodes []string fmt.Println("Start parsing review")