|
|
# 股票知识
## 趋势理论
根据道氏理论,股票价格运动有三种趋势
主要趋势、次要趋势和短暂趋势
### 主要趋势
主要趋势是股票价格广泛或全面性上升或下降的变动情形,持续时间通常为一年或以上。
从大的角度来看上涨和下跌的变动
主要趋势上升的,被称为多头市场
主要趋势下降的,被称为空头市场
#### 多头市场
多头市场是指主要趋势为上升的市场状态,也称为主要上升趋势。
三阶段:进货期->十分稳定的上升和增多的交易量->交易沸腾,成交量上升
#### 空头市场
也称为主要下跌趋势,是股票市场的一种状态,其主要特征是股价普遍下降。
三阶段:出货期->恐慌期->下跌期(继续下跌)
### 次要趋势(修正趋势)
次要趋势是主要趋势的调整,与主要趋势方向相反,持续时间从3周到数月不等。
### 短暂趋势
短暂趋势是短期的波动,很少超过三个星期,通常少于6天
每日行情的波动,
长期投资者关注股价基本趋势,投机者关注修正趋势,短暂趋势重要性小,容易受人操控,一般不关注
### 道氏理论基本要点
#### 评价价格包容消化一切
### 如何判断大趋势运行方向

通过趋势线
## 趋势理论延伸——趋势线
### 百分比回撤
通常,市场不会直线上升,也不会竖直跌落

百分比回撤+蜡烛图结合 很有用
## 股票价格的运行规律
### 股价运行规律
1. 股价应在多空双方均衡位置上下波动。 2. 原有的平衡被打破后,股价将寻找新的平衡。
持续整理保持平衡—打破平衡—新的平衡—再打破平衡-……
### 支撑线和压力线
支撑线又称为抵抗线。股价下跌到某个位置,股价停止下跌,
压力线又称为阻力线。当股价上涨到某价位附近时,股价会停止上涨

前期的高点和低点都是很重要的压力和支持
一条支撑线和压力线对当前时期股价变化影响的重要性有三方面的考虑:
1. 股价在这个区域持续时间的长短 2. 股价在这个区域伴随的成交量大小 3. 这个支撑区域或压力区域发生的时间,距离当前这个时期的远近
持续时间长,成交量大,离现在近,则影响大
### 趋势线和轨道线
#### 趋势线
趋势线是衡量价格变化趋势的
上升趋势,两个显著的低点连成一条直线,就是上升趋势线
下降趋势,两个显著的高点连成一条直线,就是下降趋势线
上升趋势线是支持线的一种下降趋势线是压力线的一种
##### 趋势线两种作用
1. 对股价今后的变动起约束 2. 趋势线被突破后,就说明股价下一步的趋势将要反向,越有效的趋势线被突破,其转势的信号越强烈
##### 怎么才算对趋势线的突破
1. 收盘价突破趋势线比日内的最高最低价突破趋势线重要; 2. 穿越趋势线后,离趋势线越远,突破越有效。人们可以根据各个股票的具体情况,自己制定一个界限,一般是用突破的幅度,如3%; 3. 穿越趋势线后,在趋势线的另一方停留的时间越长,突破越有效。
#### 轨道线
又称通道线,管道线
两条平行线组成一个轨道,这就是常说的上升和下降轨道即趋势线的平行线
管道线持续的时间越长,其意义越重大,一个长期的上升通道和下降通道被有效突破,它将代表着一个新趋势的开始。
#### 买卖法则
##### 上升趋势:一买三卖法则
一买:接触到趋势线买
三卖:接触到轨道线卖,突破管道线卖,跌破趋势线卖

##### 下降趋势:一卖三买法则
一卖:接触趋势线卖
三买:接触管道线买,跌破管道线买,突破趋势线买

# 学习内容-Gin框架的基本使用
## 下载与安装
> 更改环境变量 GOPATH
> > 方便将包下载到其他的盘符目录
> > 参考:[2024年go安装教程(Windows)包括配置GOPATH-CSDN博客](https://blog.csdn.net/weixin_63860405/article/details/139732041)
### 下载
```shell go get -u github.com/gin-gonic/gin ```

## 基础使用
### GET请求
```go package main
import "github.com/gin-gonic/gin"
func main() { router := gin.Default() router.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "Hello World!", }) }) router.Run() // 监听并在 0.0.0.0:8080 上启动服务 // 默认是在8080端口启动服务,如果8080端口被占用,则自动寻找可用端口启动服务,可以指定端口 } ```

### ANY请求
根据请求来选择(使用if else)
```go // Any 请求 router.Any("/any", func(c *gin.Context) { if c.Request.Method == "POST" { c.JSON(200, gin.H{ "message": "POST", }) } else if c.Request.Method == "GET" { c.JSON(200, gin.H{ "message": "GET", }) } else { c.JSON(200, gin.H{ "message": "Any", }) } }) ```
### POST请求
```go // POST 请求 router.POST("/post", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "POST", }) })
```

## 参数获取
### 获取query string 参数
格式:URL `?`后携带参数
例如:/user/searcher?username=xxx&address=xxx
```go // 获取参数,query string router.GET("/user/search", func(c *gin.Context) { username := c.DefaultQuery("username", "lihuibear") address := c.Query("address")
// 返回json数据 c.JSON(200, gin.H{ "username": username, "address": address, })
}) ```

### 获取 form参数
当前端请求的数据通过form表单提交时,例如向`/user/search`发送一个POST请求,获取请求数据的方式如下:
```go router.POST("/user/search_by_form", func(c *gin.Context) { // DefaultPostForm取不到值时会返回指定的默认值 //username := c.DefaultPostForm("username", "小王子") username := c.PostForm("username") address := c.PostForm("address") //输出json结果给调用方 c.JSON(http.StatusOK, gin.H{ "message": "ok", "username": username, "address": address, }) }) ```
### 获取JSON参数
当前端请求的数据通过JSON提交时,例如向`/json`发送一个JSON格式的POST请求,则获取请求参数的方式如下:
```go //获取JSON参数 router.POST("/json", func(c *gin.Context) { // 注意:下面为了举例子方便,暂时忽略了错误处理 b, _ := c.GetRawData() // 从c.Request.Body读取请求数据 // 定义map或结构体 var m map[string]interface{} // 反序列化 _ = json.Unmarshal(b, &m)
c.JSON(http.StatusOK, m) }) ```
### 获取path参数
请求的参数通过URL路径传递,例如:`/user/search/小王子/沙河`。 获取请求URL路径中的参数的方式如下:
```go // 获取path参数 router.GET("/user/search/:username/:address", func(c *gin.Context) { username := c.Param("username") address := c.Param("address") //输出json结果给调用方 c.JSON(http.StatusOK, gin.H{ "message": "ok", "username": username, "address": address, }) }) ```
### 参数绑定 ShouldBind()
为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的`Content-Type`识别请求数据类型并利用反射机制自动提取请求中`QueryString`、`form表单`、`JSON`、`XML`等参数到结构体中。
```go // 参数绑定
// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"}) router.POST("/login_by_JSON", func(c *gin.Context) { var login Login
if err := c.ShouldBind(&login); err == nil { fmt.Printf("login info:%#v\n", login) c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) // 绑定form表单示例 (user=q1mi&password=123456) router.POST("/login_by_form", func(c *gin.Context) { var login Login // ShouldBind()会根据请求的Content-Type自行选择绑定器 if err := c.ShouldBind(&login); err == nil { c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) // 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456) router.GET("/login_by_query", func(c *gin.Context) { var login Login // ShouldBind()会根据请求的Content-Type自行选择绑定器 if err := c.ShouldBind(&login); err == nil { c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) ```
`ShouldBind`会按照下面的顺序解析请求中的数据完成绑定:
1. 如果是 `GET` 请求,只使用 `Form` 绑定引擎(`query`)。 2. 如果是 `POST` 请求,首先检查 `content-type` 是否为 `JSON` 或 `XML`,然后再使用 `Form`(`form-data`)。
## Gin渲染
我们首先定义一个存放模板文件的`templates`文件夹,然后在其内部按照业务分别定义一个`posts`文件夹和一个`users`文件夹。 `posts/index.html`文件的内容如下:
```template <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>posts/index</title> </head> <body> {{.title}} </body> </html> {{end}} ```
`users/index.html`文件的内容如下:
```template {{define "users/index.html"}} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>users/index</title> </head> <body> {{.title}} </body> </html> {{end}} ```
Gin框架中使用`LoadHTMLGlob()`或者`LoadHTMLFiles()`方法进行HTML模板渲染。
```go func main() { r := gin.Default() r.LoadHTMLGlob("templates/**/*") //r.LoadHTMLFiles("templates/posts/index.html", "templates/users/index.html") r.GET("/posts/index", func(c *gin.Context) { c.HTML(http.StatusOK, "posts/index.html", gin.H{ "title": "posts/index", }) })
r.GET("users/index", func(c *gin.Context) { c.HTML(http.StatusOK, "users/index.html", gin.H{ "title": "users/index", }) })
r.Run(":8080") } ```
## 文件上传
### 单文件上传
```go // 加载模板 router.LoadHTMLFiles("./templates/upload.html") // 上传文件 router.GET("/upload", func(c *gin.Context) { c.HTML(http.StatusOK, "upload.html", nil) })
router.POST("/upload", func(c *gin.Context) { // 接收用户上传文件的post请求 f, err := c.FormFile("avatar") if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": err.Error(), }) return } // 保存到指定目录 dst dst := "./upload/" + f.Filename c.SaveUploadedFile(f, dst)
// 返回响应 c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("'%s' uploaded!", f.Filename), }) }) ```
### 多文件上传
```go // 多文件上传
// 加载模板 router.LoadHTMLFiles("./templates/uploads.html") // 显示多文件上传页面 router.GET("/multi-upload", func(c *gin.Context) { c.HTML(http.StatusOK, "uploads.html", nil) }) // 多文件上传 router.POST("/multi-upload", func(c *gin.Context) { // Multipart form form, err := c.MultipartForm() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "failed to parse multipart form"}) return }
files := form.File["file"]
for index, file := range files { log.Println(file.Filename) dst := fmt.Sprintf("./upload/%s_%d", file.Filename, index)
if err := c.SaveUploadedFile(file, dst); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } }
c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("%d files uploaded!", len(files)), }) }) ```
## 重定向
### http重定向
```go // http 重定向 router.GET("/abc", func(c *gin.Context) { c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/") }) ```
### 路由重定向
```go // 路由重定向 router.GET("/def", func(c *gin.Context) { c.Request.URL.Path = "/ping" router.HandleContext(c) })
```
## Gin路由
### 普通路由
```go r.GET("/index", func(c *gin.Context) {...}) r.GET("/login", func(c *gin.Context) {...}) r.POST("/login", func(c *gin.Context) {...}) ```
### any
```go r.Any("/test", func(c *gin.Context) {...}) ```
### 404页面
```go r.NoRoute(func(c *gin.Context) { c.HTML(http.StatusNotFound, "views/404.html", nil) }) ```
### 路由组
我们可以将拥有共同URL前缀的路由划分为一个路由组。习惯性一对`{}`包裹同组的路由,这只是为了看着清晰,你用不用`{}`包裹功能上没什么区别。
```go func main() { r := gin.Default() userGroup := r.Group("/user") { userGroup.GET("/index", func(c *gin.Context) {...}) userGroup.GET("/login", func(c *gin.Context) {...}) userGroup.POST("/login", func(c *gin.Context) {...})
} shopGroup := r.Group("/shop") { shopGroup.GET("/index", func(c *gin.Context) {...}) shopGroup.GET("/cart", func(c *gin.Context) {...}) shopGroup.POST("/checkout", func(c *gin.Context) {...}) } r.Run() } ```
路由组也是支持嵌套的,例如:
```go shopGroup := r.Group("/shop") { shopGroup.GET("/index", func(c *gin.Context) {...}) shopGroup.GET("/cart", func(c *gin.Context) {...}) shopGroup.POST("/checkout", func(c *gin.Context) {...}) // 嵌套路由组 xx := shopGroup.Group("xx") xx.GET("/oo", func(c *gin.Context) {...}) } ```
通常我们将路由分组用在划分业务逻辑或划分API版本时。
### 路由原理
Gin框架中的路由使用的是[httprouter](https://github.com/julienschmidt/httprouter)这个库。
其基本原理就是构造一个路由地址的前缀树。
# 明日计划
1. 学习Goframe框架 2. 学习股票知识
|