朝简单处想 往认真处行


  • 首页

  • 标签

  • 分类

  • 归档

朋友说他有个致富公式… 让我给看看

发表于 2022-01-16
字数统计: 731 字 | 阅读时长 ≈ 3 分钟

写在开头

主要实现的东西是:
1)朋友给了个通达信公式,想看能不能致富;
2)手动去执行选股肉眼观察,效果还行;
3)有文化的我们知道只凭肉眼看肯定不靠谱,就想回测看看效果,就去测了;

涉及知识点:通达信的公式编辑,选股,以及bigquant上的回测

通达信看效果貌似还行

选股公式是这样子的:

1
2
3
4
DIFF:=EMA(CLOSE,12) - EMA(CLOSE,26);
DEA:= EMA(DIFF,9);
MACD:= 2*(DIFF-DEA);
REF(C<=O,2) AND REF(H<REF(H,1) AND L<REF(L,1),1) AND L>REF(L,1) AND C>O AND C>REF(H,2) AND REF(EVERY(C/REF(C,1)<1,3),3) AND DIFF>0 AND DEA>0;

打开通达信,Ctrl + F , 条件选股, 新建公式
把这个公式粘贴进去, 测试公式, 保存
[图片见文末参考链接]

Ctrl T, 选择刚建好的公式,执行选股,多试几个日期,发现,哎呦不错;
[图片见文末参考链接]

那么回测试试呢?

首先需要将通达信公式语言转化成 python 语言;
回测平台选的是 bigquant, 因为我自己相对比较熟;
翻译的过程中要是有不懂的语句,网上查下(文末附链接);
然后核对的时候看选出的股票能不能对上,就能知道有没有转化正确;

1
2
3
4
5
6
7
8
# 通达信公式
DIFF:=EMA(CLOSE,12) - EMA(CLOSE,26);
DEA:= EMA(DIFF,9);
MACD:= 2*(DIFF-DEA);
REF(C<=O,2) AND REF(H<REF(H,1) AND L<REF(L,1),1) AND L>REF(L,1) AND C>O AND C>REF(H,2) AND REF(EVERY(C/REF(C,1)<1,3),3) AND DIFF>0 AND DEA>0;

# python
x.close_2 <= x.open_2 and (x.high_1 < x.high_2 and x.low_1 < x.low_2) and x.low_0 > x.low_1 and x.close_0 > x.open_0 and x.close_0 > x.high_2 and x.close_5 < x.close_6 and x.close_4 < x.close_5 and x.close_3 < x.close_4 and (x.dif > 0 and x.dea >0)

Bigquant 实现
Bigquant最后实现的效果如下,下边挑重点的截图简单说一下
[图片见文末参考链接]

1)特征列表,需要把公式里涉及的特征都体现在特征列表里边
[图片见文末参考链接]
2)自定义python模块中生成一下信号
[图片见文末参考链接]
3)回测函数中定义好自己的回测逻辑就可以回测了

回测结果
[图片见文末参考链接]

写在后边

真正能拿到财富代码的公式肯定不会这么简单,这篇只是方法的记录文章罢了;
转化公式的时候发现貌似没有通达信公式-> python语言的现成工具,感觉可以做一个;

参考链接

通达信公式
https://www.agudashi.cn/doc/5bffb706e7de95c78c41dd3c.html
公众号文章链接
朋友说他有个致富公式… 让我给看看

雪球模拟组合收益率爬取

发表于 2022-01-15
字数统计: 559 字 | 阅读时长 ≈ 2 分钟

实现的功能:

1)爬取雪球组合六个月以内,每天的累积收益率值(时间比六个月长就不给提供每天的累积收益率了);
2)每天收盘后爬取当天的累积收益率;
3)延伸 1:把上边两点加起来就能一直跟踪组合的收益率了;
4)延伸 2:设置定时脚本,写程序定时执行上边的三个步骤,就可以每天只看一眼,时间变得简单一点点;

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import requests,json

# 获取六个月内的每天累计收益率
def get_return_rate_six_month(gid, cookie):
headers = {
'authority': 'tc.xueqiu.com',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
'accept': 'application/json, text/plain, */*',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
'origin': 'https://xueqiu.com',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://xueqiu.com/performance',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
'cookie': cookie,
}

params = (
('gid', gid),
('period', '6m'), # 每次取最大就行, 时间再长不给返回每天的累计收益率...
('market', 'ALL'),
)

response = requests.get('https://tc.xueqiu.com/tc/snowx/MONI/forchart/roa.json', headers=headers, params=params)
content = json.loads(response.text)
return content['result_data']['list']

res= pd.DataFrame()
gid = 'your gid'
cookie = 'your cookies'
data = get_return_rate(gid)
for element in data:
value_dict = dict()
value_dict['return_rate'] = element['value']
value_dict['date'] = element['date']
res= ers.append(value_dict, ignore_index = True)
res.head()


# 获取每天的累积收益率
def get_accum_rate_each_day(gid, cookie):
headers = {
'authority': 'tc.xueqiu.com',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
'accept': 'application/json, text/plain, */*',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
'origin': 'https://xueqiu.com',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://xueqiu.com/performance',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
'cookie': cookie,
}

params = (
('gid', gid),
)

response = requests.get('https://tc.xueqiu.com/tc/snowx//MONI/performances.json', headers=headers, params=params)

response.encoding = "utf-8"
content = json.loads(response.text)
if content['msg'] == '请求超时,请检查网络并重试':
print("请求错误...需要更新 cookies... ")
return

accum_rate = content['result_data']['performances'][1]['accum_rate']
return accum_rate

value = get_accum_rate_each_day(gid, cookie)

补充阅读

windows 定时脚本设置
https://www.cnblogs.com/sui776265233/p/13602893.html
linux 定时脚本设置
https://www.jianshu.com/p/d93e2b177814

雪球模拟组合查询和交易脚本-python

发表于 2022-01-11
字数统计: 422 字 | 阅读时长 ≈ 2 分钟

Talk cheap, show code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import requests
import json

# 使用前需要替换 cookie 和 组合 id, 怎么找见下边截图/链接
cookie = your_cookies
group_id = yout_group_id

# 持仓查询函数
def hold_stock():
headers = {
‘authority’: ‘tc.xueqiu.com’,
‘sec-ch-ua’: ‘” Not A;Brand”;v=“99”, “Chromium”;v=“96”, “Google Chrome”;v=“96”’,
‘accept’: ‘application/json, text/plain, */*’,
# ‘accept’: ‘application/json, charset=UTF-8’,
‘sec-ch-ua-mobile’: ‘?0’,
‘user-agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36’,
‘sec-ch-ua-platform’: ‘”Windows”’,
‘origin’: ‘https://xueqiu.com’,
‘sec-fetch-site’: ‘same-site’,
‘sec-fetch-mode’: ‘cors’,
‘sec-fetch-dest’: ‘empty’,
‘referer’: ‘https://xueqiu.com/performance’,
‘accept-language’: ‘zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7’,
‘cookie’: cookie,
}

params = (
(‘gid’, group_id),
)
response = requests.get(‘https://tc.xueqiu.com/tc/snowx//MONI/performances.json’, headers=headers, params=params)
response.encoding = “utf-8”
content = json.loads(response.text)
res_stock = content[‘result_data’][‘performances’][1][‘list’]
res_asset = content[‘result_data’][‘performances’][1][‘assets’]
return res_asset, res_stock

# 交易函数
def trade(direction, date, comment, stock_code, price, shares, tax_rate):
headers = {
‘authority’: ‘tc.xueqiu.com’,
‘sec-ch-ua’: ‘” Not A;Brand”;v=“99”, “Chromium”;v=“96”, “Google Chrome”;v=“96”’,
‘accept’: ‘application/json, text/plain, */*’,
‘content-type’: ‘application/x-www-form-urlencoded’,
‘sec-ch-ua-mobile’: ‘?0’,
‘user-agent’: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36’,
‘sec-ch-ua-platform’: ‘”Windows”’,
‘origin’: ‘https://xueqiu.com’,
‘sec-fetch-site’: ‘same-site’,
‘sec-fetch-mode’: ‘cors’,
‘sec-fetch-dest’: ‘empty’,
‘referer’: ‘https://xueqiu.com/performance’,
‘accept-language’: ‘zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7’,
‘cookie’: cookie,
}
data = {
‘type’: direction, # 1 是买 2 是卖
‘date’: date,
‘comment’: comment, # 备注
‘gid’: group_id,
‘symbol’: stock_code,
‘price’: price,
‘shares’: shares,
‘tax_rate’: tax_rate, # 卖是千一, 买是 0
‘commission_rate’: ‘0.1’, # 买卖都是万一

}
response = requests.post(‘https://tc.xueqiu.com/tc/snowx/MONI/transaction/add.json’, headers=headers, data=data)

写在后边

时间少,要做的事情有很多,希望能靠谱,做事,就不废话了…

公众号链接(贴图)

雪球模拟组合查询和交易脚本-python

雪球模拟盘脚本化调仓

发表于 2021-12-15
字数统计: 540 字 | 阅读时长 ≈ 2 分钟

为啥干这个?

工作和个人需要,基于雪球模拟组合实现自动化的股票调仓,主要分几步:
1)登录雪球,创建模拟组合,手动添加股票,获取填写的 cURL;
2) 转化为 python 的 post 请求;
3)运行程序,检查结果即可;

咋干?

1)创建组合
图见公众号链接,下同
2)手动添加股票
3)开发者工具,找到添加股票的请求
4)获取 cURL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
curl 'https://tc.xueqiu.com/tc/snowx/MONI/transaction/add.json' \
-H 'authority: tc.xueqiu.com' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"' \
-H 'accept: application/json, text/plain, */*' \
-H 'content-type: application/x-www-form-urlencoded' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36' \
-H 'sec-ch-ua-platform: "macOS"' \
-H 'origin: https://xueqiu.com' \
-H 'sec-fetch-site: same-site' \
-H 'sec-fetch-mode: cors' \
-H 'sec-fetch-dest: empty' \
-H 'referer: https://xueqiu.com/performance' \
-H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6' \
-H 'cookie: your cookie here' \
--data-raw 'type=1&date=2021-12-15&gid=4383054580870984&symbol=SZ002157&price=9.49&shares=100&commission_rate=0.1' \
--compressed

5)转化python的格式
https://tool.lu/curl/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests
headers = {
'authority': 'tc.xueqiu.com',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"',
'accept': 'application/json, text/plain, */*',
'content-type': 'application/x-www-form-urlencoded',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36',
'sec-ch-ua-platform': '"macOS"',
'origin': 'https://xueqiu.com',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://xueqiu.com/performance',
'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6',
'cookie': 'your cookie here',
}

data = {
'type': '1', # 1是买,2是卖
'date': '2021-12-15',
'gid': '4383054580870984',
'symbol': 'SZ002714',
'price': '9.49',
'shares': '100',
'tax_rate': '0',
'commission_rate': '0.1'
}

response = requests.post('https://tc.xueqiu.com/tc/snowx/MONI/transaction/add.json', headers=headers, data=data)

批量处理的时候,只需要脚本处理 data 的字典内容即可,太简单了,不展开说;

注意的点

1)cookies 一段时间可能失效,需要手动更新下;
2)基金,etf 都可以;

吃水不忘挖井人

https://github.com/yyri/stockScripts

公众号链接

https://mp.weixin.qq.com/s/rIYEBCV04xL1XMky57EtPA

shell 和 windows 查找文件并且压缩

发表于 2021-11-18
字数统计: 87 字 | 阅读时长 ≈ 1 分钟

How to search files and zip(Linux or Windows)

1
find ./  -name '*.tar.zf' -exec zip filname.zip {} +
1
2
3
4
5
6

Get-ChildItem -Path D:\test -Recurse -Include *.tar.gz| Compress-Archive -Verbose -DestinationPath D:\test.zip -Force

$filepath="D:\test"
$zippath="D:\test.zip"
Get-ChildItem -Path $filepath -Recurse -Include *.tar.gz| Compress-Archive -Verbose -DestinationPath $zippath -Force

参考链接

https://www.twblogs.net/a/5b7d44a32b71770a43de7828
https://www.codegrepper.com/code-examples/shell/powershell+zip+multiple+files
https://community.spiceworks.com/topic/2239060-search-for-files-and-zip

基于另类数据对ETF进行回测

发表于 2021-11-07
字数统计: 2.2k 字 | 阅读时长 ≈ 9 分钟

基本背景

彭博盘前简报:7月14日

每天都会看这个公众号,而且会在盘前发,发现内容中提到的中概股和中概ETF的涨跌具有一定的相关性,早就手痒痒了想做一下回测看是否真得如此,于是,花了一整天时间… 有了这篇文章。

爬取公众号文章

爬取过程中三个麻烦的点:
1)可能会输入验证码;
2)爬取几次后,cookies会失效;
3)到最后即使手动查询想要查询的公众号,也会报错,返回了None(不知道是不是爬取次数过多的原因),不过弄到的数据已经够我用了(再早,这个公众号还没有中概股这个版块);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import os,re

from selenium import webdriver #引入自动化登录模块
import time,datetime #时间模块
import json
import requests #抓取信息
import random
from selenium.webdriver.common.by import By #引入定位寻找模块
from selenium.webdriver.common.keys import Keys #引入键盘动作模块
from selenium.webdriver import ActionChains #引入鼠标行为模块


# 微信公众号账号
user=""
#公众号密码
password=""
#设置要爬取的公众号列表
gzlist=['彭博环球财经']
#保存的结果文件地址
fileName="articles.xls"

#登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中
def weChat_login():
#定义一个空的字典,存放cookies内容
post={}

#用webdriver启动谷歌浏览器
print("启动浏览器,打开微信公众号登录界面")
#CHROME_DRIVER=r"F:\\chromedriver.exe"
op = webdriver.ChromeOptions()
# macos 使用的语句
driver = webdriver.Chrome(options=op)
#driver = webdriver.Chrome(executable_path=CHROME_DRIVER)
#driver.set_window_position(0,0)
#driver.maximize_window()
#打开微信公众号登录页面
driver.get('https://mp.weixin.qq.com/')
#等待5秒钟
time.sleep(10)
print("正在输入微信公众号登录账号和密码......")
driver.find_element_by_xpath("./*//a[@class='login__type__container__select-type']").click() #鼠标放到使用账号密码登录键上

#清空账号框中的内容
driver.find_element_by_xpath('//*[@id="header"]/div[2]/div/div/div[1]/form/div[1]/div[1]/div/span/input').clear()
#自动填入登录用户名
driver.find_element_by_xpath('//*[@id="header"]/div[2]/div/div/div[1]/form/div[1]/div[1]/div/span/input').send_keys(user)
#清空密码框中的内容
driver.find_element_by_xpath('//*[@id="header"]/div[2]/div/div/div[1]/form/div[1]/div[2]/div/span/input').clear()
#自动填入登录密码
driver.find_element_by_xpath('//*[@id="header"]/div[2]/div/div/div[1]/form/div[1]/div[2]/div/span/input').send_keys(password)


#自动点击登录按钮进行登录
driver.find_element_by_xpath('//*[@id="header"]/div[2]/div/div/div[1]/form/div[4]/a').click()
# 拿手机扫二维码!
print("请拿手机扫码二维码登录公众号")
time.sleep(20)
print("登录成功")
#重新载入公众号登录页,登录之后会显示公众号后台首页,从这个返回内容中获取cookies信息
driver.get('https://mp.weixin.qq.com/')
#获取cookies
cookie_items = driver.get_cookies()

#获取到的cookies是列表形式,将cookies转成json形式并存入本地名为cookie的文本中
for cookie_item in cookie_items:
post[cookie_item['name']] = cookie_item['value']
cookie_str = json.dumps(post)
with open('cookie.txt', 'w+', encoding='utf-8') as f:
f.write(cookie_str)
print("cookies信息已保存到本地")


def get_content(query):
#query为要爬取的公众号名称
#公众号主页
url = 'https://mp.weixin.qq.com/'
#设置headers
header = {
"HOST": "mp.weixin.qq.com",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0"
}

#读取上一步获取到的cookies
with open('cookie.txt', 'r', encoding='utf-8') as f:
cookie = f.read()
cookies = json.loads(cookie)

#登录之后的微信公众号首页url变化为:https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=1849751598,从这里获取token信息
response = requests.get(url=url, cookies=cookies)
token = re.findall(r'token=(\d+)', str(response.url))[0]

#搜索微信公众号的接口地址
search_url = 'https://mp.weixin.qq.com/cgi-bin/searchbiz?'
#搜索微信公众号接口需要传入的参数,有三个变量:微信公众号token、随机数random、搜索的微信公众号名字
query_id = {
'action': 'search_biz',
'token' : token,
'lang': 'zh_CN',
'f': 'json',
'ajax': '1',
'random': random.random(),
'query': query,
'begin': '0',
'count': '5'
}
#打开搜索微信公众号接口地址,需要传入相关参数信息如:cookies、params、headers
search_response = requests.get(search_url, cookies=cookies, headers=header, params=query_id)
#print(search_response)
#取搜索结果中的第一个公众号
lists = search_response.json().get('list')[0]
print(lists)
#获取这个公众号的fakeid,后面爬取公众号文章需要此字段
fakeid = lists.get('fakeid')

#微信公众号文章接口地址
appmsg_url = 'https://mp.weixin.qq.com/cgi-bin/appmsg?'
#搜索文章需要传入几个参数:登录的公众号token、要爬取文章的公众号fakeid、随机数random
query_id_data = {
'token': token,
'lang': 'zh_CN',
'f': 'json',
'ajax': '1',
'random': random.random(),
'action': 'list_ex',
'begin': '0',#不同页,此参数变化,变化规则为每页加5
'count': '5',
'query': '',
'fakeid': fakeid,
'type': '9'
}
#打开搜索的微信公众号文章列表页
appmsg_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data)
print(appmsg_response.json())
#获取文章总数
max_num = appmsg_response.json().get('app_msg_cnt')
print(max_num)
#print(max_num)
#每页至少有5条,获取文章总的页数,爬取时需要分页爬
num = int(int(max_num) / 5)
#print(num)
#起始页begin参数,往后每页加5
begin = 0
while num + 1 > 0 :
query_id_data = {
'token': token,
'lang': 'zh_CN',
'f': 'json',
'ajax': '1',
'random': random.random(),
'action': 'list_ex',
'begin': '{}'.format(str(begin)),
'count': '5',
'query': '',
'fakeid': fakeid,
'type': '9'
}
print('正在翻页:--------------',begin)

#获取每一页文章的标题和链接地址,并写入本地文本中
query_fakeid_response = requests.get(appmsg_url, cookies=cookies, headers=header, params=query_id_data)
print(query_fakeid_response)
fakeid_list = query_fakeid_response.json().get('app_msg_list')
#print(fakeid_list)
for item in fakeid_list:
content_link=item.get('link') #链接
content_title=item.get('title') #题目
# 我只需要盘前简报
if re.search('彭博盘前简报', content_title):
print(content_title)
update_time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item.get('update_time'))) #发布时间
#print(content_title+"\t"+content_link+"\t""+update_time+"\n"))
with open(fileName,'a',encoding='utf-8') as fh:
fh.write(content_title+"\t"+content_link+"\t"+update_time+"\n")
num -= 1
begin = int(begin)
begin+=5
time.sleep(2)


if __name__=='__main__':
try:
#登录微信公众号,获取登录之后的cookies信息,并保存到本地文本中
weChat_login()
#登录之后,通过微信公众号后台提供的微信公众号文章接口爬取文章
for query in gzlist:
#爬取微信公众号文章,并存在本地文本中
print("开始爬取公众号:"+query)
get_content(query)
print("爬取完成")
except Exception as e:
print(str(e))

本部分参考链接

python爬取公众号历史文章_牛客博客
python爬取公众号阅读量_Python爬取微信公众号文章以及在看阅读数_weixin_39688870的博客-CSDN博客

处理数据

需要的文件:
1)上文爬到的结果文件;
2)中概ETF 513050的行情信息,由通达信导出;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import pandas as pd
from bs4 import BeautifulSoup
import numpy as np


dt = pd.read_table('articles.csv', header = None)

# 按需处理数据
dt = dt.drop_duplicates()
dt = dt[[ True if re.search('彭博盘前简报', x) else False for x in dt[0]]]

df = pd.DataFrame(columns = ['date', 'change'])
for index in range(0, dt.shape[0]):
#print(dt[1])
url = list(dt[1])[index]
date = list(dt[2])[index][:10]
res = requests.get(url)
soup = BeautifulSoup(res.content, "html.parser")
content = soup.get_text()
#match = re.search('(中概股:.*)美国债市', content)
# 这里我只使用了金龙中国指数作为测试
match1 = re.search('金龙中国指数上涨(\d\.\d?)%', content)
match2 = re.search('金龙中国指数下跌(\d\.\d?)%', content)
row = dict()
change = 0
if match1:
change = float(match1.group(1))

if match2:
change = 0 - float(match2.group(1))

row = {'date': date, 'change': change}
df = df.append(row, ignore_index=True)

df['date'] = pd.to_datetime(df['date'])
df = df.set_index('date')
df = df[df.change != 0]
df = df.drop_duplicates()

# etf 行情
price = pd.read_table('513050.xls')
new_column = [x.strip() for x in price.columns]
price.columns = new_column
price['date'] = pd.to_datetime(price['时间'], format='%Y/%m/%d')
# 计算每日开盘买入,收盘价卖出的话,收益率多少
price['etf_change'] = (price['收盘'] - price['开盘'])/price['开盘']*100
price = price[['date', '开盘', '收盘', 'etf_change']]
price = price.set_index('date')

# 合并数据,看下信合和场内的etf日涨跌幅是否有关系?
# 这边看效果不太好,可能和有缺失值相关
dm = pd.concat([price, df], join = 'inner', axis = 1)
fig = plt.figure(figsize = (20,8))
dm.change.plot(color = 'blue',kind = 'bar', alpha = 0.2)
dm.etf_change.plot(color = 'red', kind = 'bar', alpha = 0.2)

# 输出信号文件
# 信号日期往前推一天
dm['date'] = [x - np.timedelta64(1, 'D') for x in dm.index]
dm = dm.set_index('date')
dm['instrument'] = '510500.HOF'
dm.to_csv('signal.csv')

涨跌幅是否一致,画了个图,不是很一致…
不过,大过年的,来都来了… 就再回测一把吧….

回测平台回测

使用的平台是bigquant,交易逻辑很简单,还有优化的空间:
1)当信号大于1时,买入;
2)如果买入后第二天有信号,且信号小于0才卖出,否则不卖出; 如果没有 信号,则直接卖出;

回测有 4.25% 的收益率,跑赢基准 7个点 +.+

总结

其实我觉得公众号的能源和油气也可以试试,不过观察来看华宝油气一般开盘价就是最高点,不给买入的机会…. 后边再试试;
算是对自己观察所得另类数据的一个小尝试吧,有好多东西要学习啊啊啊啊啊啊啊…..

勤劳

发表于 2021-10-30
字数统计: 1.8k 字 | 阅读时长 ≈ 5 分钟

写在前边

觉得自己有些懒了,找些片段记录下,补充一下。
这就像饿了,去觅食一样。

之前做数据分析的时候,可视化会用到云图,简单来说就是基于文本内容统计词频,然后频率越高,字号越大,表达一下该词的重要性。

那我想读书也可以,以某一个专题去摘录一些片段,如果能略有收获,那再好不过。

勤

我一直保持全勤(我从不过什么圣礼拜一),所以得到师傅的器重,再加上我排字麻利得不是一般,于是所有的急活都派给我干,这种活一般来说,拿钱要多一点。所以这一段日子我过得十分惬意。

等我把版拆开,将铅字在字盘里归好位等第二天用时,已经是夜里十一点了,有时候还要晚:因为别的朋友还会时不时地送来一些零活,我们只好往后拖。
但我下定决心每天仍然排印一张对开纸,结果有天夜里,我已经锁定印版,以为一天的工作结束了的时候,不小心把一个印版碰坏了,有两页铅字乱得一塌糊涂,我马上拆版重排,排好了才上床睡觉。我们这样勤奋苦干,邻居们有目共睹,我们开始赢得了声望和信誉;我还听说商界的夜夜俱乐部有人提起新开张的印刷所(指的是富兰克林新开的),普遍的看法是必死无疑,因为当地已经有了凯默和布雷福德两家印刷所;然而贝尔德博士(多年以后你我在苏格兰他的故乡圣安德鲁斯见过他)则力排众议;因为那个富兰克林的勤奋,他说,是他的同行们望尘莫及的:我离开俱乐部回家时,他还在干活呢;他的邻居还没有起床,他又在工作了。

为了确保我作为一个生意人的信誉和人格,我处处留心,不仅要实打实的勤奋节俭,而且在面子上也避免有相反的表现。我衣着朴素;从不到娱乐场消闲鬼混;我从不出去钓鱼打猎;的确,看书有时候使我忘乎所以,误了正事;不过这种情况非常罕见,又十分隐蔽,没有引起物议:为了证明我不是个甩手掌柜,有时候我把从商店买来的纸张用手推车推过大街小巷送到家中。这样一来,人们认为我是个勤奋、发达的青年,买东西按时付款,进口文具的商人拉我做他们的客户,别的商人提议给我供书代销,我的事业顺风顺水。

小时候,父亲对我谆谆教导,所罗门的一句箴言被屡屡重复:“你看见办事殷勤的人吗?他必站在君王面前,必不站在下贱人面前。”从那时候起,我就把勤奋看成谋求财富和功名的手段,这句话给我很大的鼓励:尽管我并不认为我真的要站在君王面前,不过,后来这种事还真的发生了。——因为我曾在五位君王面前站过,甚至还有幸坐下来跟一位丹麦国王同席共餐。

六,勤奋。
珍惜时光。手里总忙有益之事。剪除一切无谓之举。
(路过:这里是富兰克林列出来的有必要让自己遵守和养成习惯的十三种美德,勤奋是第六项)

节俭和勤奋,使我摆脱了剩下的债务,获得了独立和富裕,所以使我更容易实施诚信和正义等等。

把长期持续的健康归功于节制,它至今还给他留下一副好身板。多亏了勤奋和节俭,他早年景况顺遂,获取了财富,还学得了种种知识,使他成为一位有用的公民,为他在学术界赢得了一定的声誉。他把祖国委任他的光荣职务归功于诚信和正义。这一整套美德,哪怕还处在他能获得的那种不完善的状态下,也多亏了它们的联合影响,使他能够脾气平和,谈笑风生,所以他一直人缘很好,甚至深得年轻朋友的喜欢。所以我希望我的某些子孙不妨学习学习,从中获得好处。

怠惰使万事艰难,勤勉使一切便当,穷理查就是这么说的;起得晚就得整天奔波,到天黑还赶不完自己的工作。懒惰走路慢腾腾,穷困赶上快如风,我们在穷理查的历书上读到的就是这样。他还说,必须人逼事,勿让事逼人。睡得早,起得早,富裕、聪明、身体好。

我想我听到你们有些人说,难道一个人不可有闲暇吗? 朋友,我要告诉你穷理查的话:要想得到闲暇,就好好利用时光。既然你对一分钟没有把握,就别丢掉一小时。闲暇是准备做有益的事情的时光。这种闲暇,勤奋的人会得到,懒汉却永远不会有。所以穷理查说,闲暇的生活与懒惰的生活是两码事。

认为怠惰比勤奋更能使你舒畅吗?不,因为穷理查说:懒惰生烦恼,安逸惹酸苦。不劳力的人只靠智谋生活,会因主干不牢而摧折。勤奋给人舒适、富足和尊敬。

以上全部摘录于《富兰克林自传》

写在后边

我为什么要做这样的摘录,并且把后边把因为勤劳而获得的好处也加粗了呢? 富兰克林是这么说的:

我之所以这样毫无顾忌地强调自己的勤奋,尽管有自吹自擂之嫌,目的无非是让读过它的子孙后代们看到在这段叙述中勤奋产生的于我有利的效果时,就可以知道这种美德的用处了。

看了就能记住吗?记住就能做到吗?真得会有效果吗?富兰克林是这么说的:

然而,总体来讲,虽然我从来没有达到我曾经雄心勃勃要达到的那种完美境界,而且还相去甚远,但我通过努力成为一个比较优秀、比较快乐的人,若不努力我是做不到这一步的;就像有些人临摹字帖,一心要练就一笔好字,尽管他们永远达不到他们希望达到的字帖的那种优秀水准,但通过努力书法大有长进,字写得漂亮清晰,也算说得过去了。

其他人的传记里,也有不少,篇幅原因,记录到这里;

2021年10月30日 @XA

詹姆斯·西蒙斯

发表于 2021-10-24
字数统计: 1.6k 字 | 阅读时长 ≈ 5 分钟

Timeline

出生
1938年4月25日,生于波士顿郊区牛顿镇,是一个制鞋厂老板的儿子,3 岁就立志成为数学家。

从牛顿高中牛业后,他进人麻省理工学院,从师于著名的数学家安布罗斯和辛格。

20岁
1958年,他获得了学士学位。

23岁
仅仅三年(1961年)后,他就拿到了加州大学伯克利分校的博士学位。

24岁
一年后(1961年)他成为哈佛大学数学系的教授。

早在1961年,他和麻省理工学院的同学投资于哥伦比亚地砖和管线公司;在伯克利,他尝试做股票交易,但是交易结果并不太好。

27岁
1964年,他离开了大学校园,进人美国国防部下属的一个非营利组织一国防逻辑分析协会,并进行代码破解工作。没过多久,《时代周刊》上关于越南战争的残酷报道让他意识到他的工作实际上正在帮助美军在越南的军事行动,反战的他于是向《新闻周刊》写信说应该结束战争。当他把反战想法告诉老板时,很自然地就被解雇了。他又回到了学术界,成为纽约州立石溪大学的数学系主任,在那里做了8年的纯数学研究。

37岁
1974年,他与陈省身联合发表了著名的论文《典型群和几何不变式》,创立了著名的陈-西蒙斯理论,该几何理论对理论物理学具有重要意义,广泛应用于从超引力到黑洞。

38岁
1976年,西蒙斯获得了每5年一次的全美数学科学维布伦奖金,这是美国数学世界里的最高荣耀。

(在理论研究之余,他开始醉心于股票和期货交易。)

40岁
1978年,他离开石溪大学创立私人投资基金 Limroy,该基金投资领城广江,涉及从风险投资到外汇交易;最初主要采用基本面分析方法,例如,通过分析美联储货币政策和利率走向来判断市场价格走势。

50岁
十年后(1988年),西蒙斯决定成立一个纯粹量化投资的对冲基金。他关闭了Limroy,并在1988年3月成立了大奖章基金,最初主要涉及期货交易。

1988年该基金盈利8.8%。

51岁
1989年则开始亏损,西蒙斯不得不在 1989年6月份停止交易。在接下来的6个月中,西蒙斯和普林斯顿大学的数学家勒费尔重新开发了交易策略,并从基本面分析转向量化分析。

(大奖章基金主要通过研究市场历史资料来发现统计相关性,以预测期货、货币、股票市场的短期运动,并通过数千次快速的日内短线交易来捕捉稍纵即逝的市场机会,交易量之大甚至有时能占到整个纳斯达克交易量的10%。当交易开始时,交易模型决定买卖品种和时机,20名交易员则遵守指令在短时间内大量地交易各种美国和海外的期货,包括商品期货、金融期货、股票和债券。但在某些特定情况下,比如市场处在极端波动的时候,交易会切换到手工状态。)

55岁
经过几年眩目的增长,大奖章基金在1993年达到2.7亿美元,并开始停止接受新资金。

56岁
1994年,西蒙斯的文艺复兴科技公司从12个雇员增加到36个,并交易40种金融产品。

74岁
现在(书的印刷时间2012年),公司有150个雇员,交易60种金融产品,基金规模则有50 亿美元。在150名雇员中有三分之一是拥有自然科学博士学位的顶尖科学家,涵盖数学、理论物理学、量子物理学和统计学等领域。所有雇员中只有两位是华尔街老手,而且该公司既不从商学院中雇用职员,也不从华尔街雇用职员,这在美国投资公司中几乎是独一无二的。

成就

无论是1998年俄罗斯债券危机,还是本世纪初的互联网泡沫,大奖章基金历经数次金融危机,始终屹立不倒,令有效市场假说都黯然失色。

1989年到2009年间,他操盘的大奖章基金平均年回报率高达35%,较同期标普500指数年均回报率高20多个百分点,比金融大鳄索罗斯和股神巴菲特的操盘表现都高出10余个百分点。

即便是在次贷危机爆发的2008年,该基金的回报率仍高达80%。从2002年底至2005年底,规模为50亿美元的大奖章基金己经为投资者支付了60多亿美元的回报。

这个回报率是在扣除了5%的资产管理费和44%的投资收益分成以后得出的,并且己经经过了車计。值得一提的是,西蒙斯收取的这两项费用应该是对冲基金界最高的,相当于平均收费标准的两倍以上。

语录

和流行的 “买人并长期持有”的投资理念截然相反,西蒙斯认为市场的异常状态通常都是微小而且短暂的,‘’我们随时都在买人卖出和卖出买人,我们依靠活跃赚钱‘’,西蒙斯说。

“文艺复兴科技公司没有也不需要那么高的杠杆比例,公司在操作时从来没有任何先人为主的概念,而是只寻找那些可以复制的微小的获利瞬间,我们绝不以 “市场恢复正常’作为赌注投人资金,有一天市场终会正常的,但谁知道是哪一天。”

西蒙斯透露,公司对交易品种的选择有3个标准:即公开交易品种、流动性高,同时符合模型设置的某些要求。他表示:“我是模型先生,不想进行基本面分析。模型的最重要的优势是可以降低风险。而依靠个人判断选股,你可能一夜暴富,也可能在第二天又输得精光。”

摘录自《量化投资-技术与策略》

uqer实现期现套利

发表于 2021-10-23
字数统计: 792 字 | 阅读时长 ≈ 3 分钟

核心思想是股指期货和指数的基差会周期性变化,那么贴水的时候持有股指期货,升水的时候持有指数的可交易标的,可以实现套利的目的。

分三步:

  1. 基于分钟行情计算基差;
  2. 上传到有uqer生成交易逻辑,进行回测;
  3. 中间踩了不少坑,时间关系不细说;

总体来说,实现期现套利的过程比较麻烦,bigquant上不能跨品种回测,而uqer普通用户有没有分钟行情数据(但是可以自己上传信号文件实现目的),然后内存太小了,也没法很好的进行后续的参数优化,最终能实现大概10%的年化,16.2%的回撤。

主要是记录一下,脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 期现套利
import pandas as pd
start = '2017-01-01' # 回测起始时间
end = '2021-09-22' # 回测结束时间
benchmark = 'ZZ500' # 策略参考标准
universe = ['510500.XSHG'] + ['ICM0'] # 证券池,也可以在这里添加多个证券, M0 主力合约, L0 当月合约
capital_base = 1000000 # 起始资金, 期货和etf各100w
freq = 'm' # 日线策略
refresh_rate = 1 # 每个交易日调仓

# 账户初始化配置
stock_commission = Commission(buycost=0, sellcost=0, unit='perValue')
futures_commission = Commission(buycost=0.000023, sellcost=0.000023, unit='perValue')
slippage = Slippage(value=0, unit='perValue')
#argin_rate = {'IC': 0.20}

accounts = {
'stock_account': AccountConfig(account_type='security', capital_base=capital_base, commission=stock_commission, slippage=slippage),
'futures_account': AccountConfig(account_type='futures', capital_base=capital_base, commission=futures_commission, slippage=slippage)
}

# 读取文件
dt = pd.read_csv('基差_etf1.csv')
dt = dt.set_index('date')

date_list = list()

stock_buy_date = list()
fut_buy_date = list()

stock_sell_date = list()
fut_sell_date = list()

# 贴水阈值
low_value = -20
# 升水阈值
high_value = 15

# 移仓日ic不交易
change_date = list()

def initialize(account):
pass

def handle_data(account):
stock_account = account.get_account('stock_account')
future_account = account.get_account("futures_account")
today = account.now.strftime('%Y-%m-%d')
minu = account.now.strftime('%Y-%m-%d %H:%M:%S')
#print(minu)
#print(type(minu))
if minu not in dt.index:
return
else:
basis = dt.loc[minu].basis
stock_pos = stock_account.get_positions()
future_pos = future_account.get_positions()

# etf
etf = '510500.XSHG'

# 获取主连, 映射
main_contract_IC = account.get_symbol('ICM0')

# 检查是否换合约
if account.mapping_changed('ICM0'):
symbol_before, symbol_after = account.get_rolling_tuple('ICM0')
#rint(symbol_before, 'changed to', symbol_after)
Position = future_account.get_position(symbol_before)
if Position> 0:

#print(minu, ': switch', symbol_before, symbol_after)

future_account.switch_position(symbol_before, symbol_after) #移仓指令
change_date.append(today)

#basis = DataAPI.MktFutIdxBasisGet(secID=u"",ticker=main_contract_IC,beginDate=today,endDate=today,field=['basis'],pandas="1")['basis'].iloc[0]
# 买卖etf
# 升水的时候买etf, 买入后
if basis >= high_value and etf not in stock_account.get_positions() and today not in stock_buy_date:
#print(minu, 'buy etf', basis, account.current_price(etf))
amount = int(stock_account.cash/account.current_price(etf) / 100) * 100
# 计算买入数量
#print('numbers:', amount)
stock_account.order_pct(etf, 0.99)
stock_buy_date.append(today)
#stock_account.order(etf, 10000)
# 贴水的时候卖etf , 卖出后不再卖出
elif basis <= low_value and etf in stock_account.get_positions() and today not in stock_buy_date and today not in stock_sell_date:
#print(minu, 'sell etf', basis, account.current_price(etf))
stock_account.order_to(etf, 0)

stock_sell_date.append(today)

# 买卖期货, 分开写,逻辑清晰一些
if basis >= high_value and main_contract_IC in future_account.get_positions() and today not in fut_sell_date and today not in fut_buy_date and today not in change_date:
# 当天买入后,不再卖出
# 当天卖出后,不再卖出..
#print(minu, 'sell ic', basis, account.current_price(main_contract_IC))
future_account.order(main_contract_IC, -1, 'close')
fut_sell_date.append(today)
elif basis <= low_value and main_contract_IC not in future_account.get_positions() and today not in fut_buy_date and today not in change_date:
# 当天买入后,不再买入
#print(minu, 'buy ic', basis, account.current_price(main_contract_IC))
future_account.order(main_contract_IC, 1, 'open')
fut_buy_date.append(today)
'''
stock_pos = stock_account.get_positions()

print('==========================', minu , '============================================')
print('stock position:')
print(stock_pos)
print('stock cash:')
fut_pos = future_account.get_positions()
print('future position:')
print(fut_pos)
print(stock_account.pending_blotter)
print(account.current_price(etf))
print('---------------------------------------------------------------------------------')
'''

选择的可能性

发表于 2021-08-15
字数统计: 1k 字 | 阅读时长 ≈ 3 分钟

写在前边

关注的一个博主说最近做决策时的两个标准:
1)选择难的;
2)选择带来更多可能性的。

想说说第二个,我觉得很多不同领域的道理是相通的。

比如投资里边有个概念:很多新手关注收益率,其实更重要的是资产配置和风险管理。所以你要按照风险偏好买股票,买债券,买货基,还有活期保险等,配置不同的仓位以及不买P2P这种可能把老本赔没了的产品。

工作也是,上一份工作加班特别多,大量地消耗自己的时间,身体和精力。既然投资需要资产配置,那为啥可以让一份工作占据了自己所有的生活和时间。前同事们以调侃的方式说掉头发,说自己体检的异常项越来越多,我不知道有啥好笑的,甚至有点儿害怕(误)。

生活和关系也是咯,不把自己「押」在一种生活方式(反例是:之前女性的家庭主妇)和一种人际关系。

爱情,友情,亲情统统都要,让这些”行星”以一种合理的方式绕着自己的系统。(反例是:最近因为分手上热搜的事情。我觉得可以,但是没必要,不应该让自己因为一个人走丢了就溃不成兵。)

所有的这些我觉得都可以归纳为可能性。

小孩子比大人有更多可能性(知道这个道理后,我就从来不会觉得小孩子是小孩子);

有钱比没钱有更多可能性(所以我开始省钱);

城里的人比俺们村里的人有更多可能性(所以俺挺羡慕他们接了一手好牌,但是牌怎么打看自己)。

属于自己的时间多比少有更多的可能性,所以我辞职了(也有其他原因)。
现在的问题在于:我能不能把这多出来的时间做出来新的可能性,我不知道… 方向是这个。

One more thing: 投资里还有个概念,说与其自己乱买股票,不如买宽基,行业ETF(甚至是定投的方式), 深以为然。同理,如果不知道自己想要什么样的生活,可以试着大概按照大多数人的生活方式去生活(该读书时读书,该工作时工作),至少不会出大错,免得被生活教做人。 如果天赋异禀,另说。


以下是简短的读书摘要,还是曹德旺的《心若菩提》:

离开了学校,仍然想读书,怎么办呢? 我就捡哥哥读过的书念。哥哥大我两岁。但和我不同,他从小就是个乖孩子,很听话。母亲和老师都喜欢他。

还想读书却不能读了。我就把哥哥读过的书带在身边,边放牛边捡柴之余边自学。看不懂的字,就问哥哥。 哥哥不在身边时,就用《新华字典》和《辞海》查找。

那时的《字典》一本8角钱,是割了一年多的马草攒下的;《辞海》3元钱,是割了三年多的马草才攒够了钱买下的。我靠字典自学读书的习惯,就是这样养成的。一个一个的字,从它们认得我到我认得它们,也是这么一字一字查出来的。

那时,只要是印有字的纸,我都会拿起来读,我的很多知识的积累,都来自于这样的自学。一直到现在,我仍然爱看各种书籍,并有一个怪癖到我家千万别向我借书或要书,再好的朋友我都不会给,真是有一点爱书如命。

写在后边

读书也是增加了可能性,特别是人就那么点儿时间。
记录是为了更好的审视自己。
以上

2021年8月15日 下午1:27 @XA
记录是为了更好地审视自己

123…9

Nonewood

90 日志
3 分类
59 标签
© 2024 Nonewood | Site words total count: 144.4k
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4