哲学喵量化管理系统——帮助你10分钟实现自己的管理系统
记得以前其实很想要一套web管理系统,但是那时候对前端这些知识一窍不通,最近在制作一套讲这个内容的课程,在示例项目完成之后就在想,其实可以写一个网站,提供一套模板,然后用户只要对接数据就可以把数据显示出来,所以就有了这个小项目。前提是你有一定的python基础,能够做一些非常基本的数据处理,网站只会保存你的用户名和密码以及你提供的接口的信息,除此之外的数据都不会做任何记录,因此不会有数据安全等问题,其实呢这些数据也只是对你个人有意义,对于别人也是没有任何价值的。
首先得在我们网站上注册一个账号,网址是:control.mrocket.cn
可以先用我的账号看一下效果:
- 账号:garyhertel@foxmail.com
- 密码:123456
然后可以先把示例项目跑起来:
import datetime
import json
import pandas
from flask import Flask
from flask import request
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources=r'/*')
@app.route("/get_my_dashboard_bar_chart_data")
def get_my_dashboard_bar_chart_data():
"""首页柱状图数据"""
data = {
"name": "Gary的持仓市值",
"timestamps": ["2022-01-01 00:00:00", "2022-02-01 00:00:00", "2022-03-01 00:00:00", "2022-04-01 00:00:00", "2022-05-01 00:00:00"],
"data": [1, 2, 3, 4, 5]
}
return data
@app.route("/get_my_dashboard_gauge_chart_data")
def get_my_dashboard_gauge_chart_data():
"""首页仪表图数据"""
data = {
"name": "Gary的账户风险",
"data": 77
}
return data
@app.route("/get_my_dashboard_pie_chart_data")
def get_my_dashboard_pie_chart_data():
"""首页饼图数据"""
data = {
"name": "Gary的持仓分布",
"data": [
{"name": "贵州茅台", "value": 170},
{"name": "三一重工", "value": 240},
{"name": "长春高新", "value": 133},
{"name": "水井坊", "value": 88},
]
}
return data
@app.route("/get_my_dashboard_line_chart_data")
def get_my_dashboard_line_chart_data():
"""首页折线图数据"""
# 只需修改data就可以,替换成自己的数据
data = {
"name": "Gary的资金走势图",
"timestamps": ["2022-01-01 00:00:00", "2022-02-01 00:00:00", "2022-03-01 00:00:00", "2022-04-01 00:00:00",
"2022-05-01 00:00:00", "2022-06-01 00:00:00", ],
"data": [100, 200, 300, 250, 150, 800]
}
asset_range = request.args.get("asset_range") # 获取get请求参数
# 根据时间范围筛选对数据做处理
df = pandas.DataFrame({"d": data["data"]}, index=data["timestamps"])
df.index = pandas.to_datetime(df.index)
if asset_range == "今日":
today_date = data["timestamps"][-1][0: 10]
today_df = df.loc[today_date]
dt = pandas.to_datetime(today_df.index).strftime('%Y-%m-%d %H:%M:%S').tolist()
d = today_df["d"].values.tolist()
data["timestamps"] = dt
data["data"] = d
elif asset_range == "全部":
data = data
else:
n = int(asset_range.lstrip("近").rstrip("日"))
today_date = data["timestamps"][-1][0: 10]
today_datetime = datetime.datetime.strptime(today_date, '%Y-%m-%d')
seven_day_before = today_datetime + datetime.timedelta(days=-n)
this_df = df.loc[seven_day_before: today_datetime]
dt = pandas.to_datetime(this_df.index).strftime('%Y-%m-%d %H:%M:%S').tolist()
d = this_df["d"].values.tolist()
data["timestamps"] = dt
data["data"] = d
return data
@app.route("/get_my_line_chart_data")
def get_my_line_chart_data():
"""漂亮的单独的折线图数据"""
data = {
"name": "Gary的资金曲线图",
"unit": "USDT ", # 通过加空格的方式来调整其位置和下面的数字对齐
"timestamps": ["2022-01-01 00:00:00", "2022-02-01 00:00:00", "2022-03-01 00:00:00", "2022-04-01 00:00:00", "2022-05-01 00:00:00", "2022-06-01 00:00:00"],
"data": [
{"name": "OKX", "data": [100, 200, 300, 400, 500, 600]},
{"name": "Binance", "data": [100, 200, 150, 90, 300, 50]},
{"name": "Stock", "data": [1000, 900, 800, 700, 400, 300]}
]
}
return data
@app.route("/get_my_news")
def get_my_news():
"""资讯数据, 排列顺序按data中列表的顺序,所以顺序可以自己处理一下"""
data = {
"data": [
{"timestamp": "2022-11-03 01:43:18", "data": "【格林斯潘:明年美元还能走强,即使美联储不加息也没关系】金十数据11月3日讯,前美联储主席格林斯潘预计,即使美联储放慢或停止当前的加息行动,美元明年还是会得到“助力”。现任Advisors Capital Management高级经济顾问的格林斯潘评论称:“即使像一些预测者所预期的那样,通胀在2023年上半年见顶并且美联储放慢甚至停止加息步伐,货币政策对美元而言仍然是顺风”。格林斯潘表示,美联储的加息轨迹比许多其他国家更为陡峭,这一直对美元是个上升动力。格林斯潘认为,未来支持美元走强的主要因素可能是美联储的缩表行动。此外,美元供应料将稳步下降,这也利于提升美元价值。"},
{"timestamp": "2022-11-03 00:32:21", "data": "【我国科学家在小型化相干光源研究中取得突破性进展】中国科学院上海光学精密机械研究所在小型化自由电子相干光源研究领域取得突破性进展,科研人员实现了一种新型小型化相干光源,相关研究成果今天(11月3日)在《自然》期刊发表。相干光源是方向性准直、能量高、单色性好的激光,一直以来,提高激光的辐射功率、追求更宽可调谐的频谱,以及实现体积更小、成本更低的光源都是激光科学领域的目标。该项研究获取的新型激光,把原本低亮度、低能量的表面光变成了高能量的表面激光,在通讯、传感、光谱测量、信息处理等领域具有重要意义。(央视)"},
{"timestamp": "2022-11-02 23:23:59", "data": "【受台风“尼格”影响,横琴口岸暂停办理出入境手续】 澳门治安警察局11月2日晚间表示,受台风“尼格”影响,澳门气象部门于21时30分发布“八号风球”信号。经珠澳两地口岸管理部门协商,横琴口岸于22时40分暂停办理旅客出入境手续,通关人士暂时不能通过横琴口岸过关。为确保行车安全,澳门治安警察局还将于23时封闭三条跨海大桥和莲花大桥,并已于22时30分开启西湾大桥下层车道。(央视新闻)"}
]
}
return data
@app.route("/get_my_orders")
def get_my_orders():
"""订单数据"""
data = {
"data": [
{
"platform": "OKEx",
"symbol": "BTC/USDT",
# "order_no": 'AceAFCeC-C4c9-D36d-cAbE-B774dA',
"action": "买入",
# "order_type": "市价",
"price": 100,
"quantity": 2,
"filled_qty": 30,
"remain": 70,
"status": '已完成',
"avg_price": 99,
"fee": 1,
"timestamp": "2022-01-01 18:00:00",
},
{
"platform": "Binance",
"symbol": "贵州茅台",
# "order_no": '01763939022',
"action": "卖出",
# "order_type": "限价",
"price": 200,
"quantity": 10,
"filled_qty": 100,
"remain": 100,
"status": '已撤销',
"avg_price": 2000,
"fee": 100,
"timestamp": "2022-02-01 14:00:00",
},
{
"platform": "Binance",
"symbol": "贵州茅台",
# "order_no": '01763939022',
"action": "卖出",
# "order_type": "限价",
"price": 200,
"quantity": 10,
"filled_qty": 100,
"remain": 100,
"status": '已提交',
"avg_price": 2000,
"fee": 100,
"timestamp": "2022-03-01 14:00:00",
},
{
"platform": "Binance",
"symbol": "贵州茅台",
# "order_no": '01763939022',
"action": "卖出",
# "order_type": "限价",
"price": 200,
"quantity": 10,
"filled_qty": 100,
"remain": 100,
"status": '部分成交',
"avg_price": 2000,
"fee": 100,
"timestamp": "2022-04-01 14:00:00",
}
]
}
return data
@app.route("/handle_my_order", methods=["POST"])
def handle_my_order():
"""处理订单"""
data = json.loads(request.get_data())
print("根据接收到的数据进行一些操作:", data)
return {
"msg": "订单处理成功!"
}
@app.route("/get_my_positions")
def get_my_positions():
"""持仓数据"""
data = {
"data": [
{
"platform": "OKEx",
"symbol": "BTC/USDT",
"direction": "多头",
"price": 20000,
"quantity": 2,
"profit": 99,
"ratio": 5,
"timestamp": "2022-01-01 18:00:00",
},
{
"platform": "Binance",
"symbol": "ETH/USDT",
"direction": "空头",
"price": 1000,
"quantity": 10,
"profit": -88,
"ratio": -8,
"timestamp": "2022-02-01 18:00:00",
},
{
"platform": "Stock",
"symbol": "贵州茅台",
"direction": "多头",
"price": 1800,
"quantity": 100,
"profit": 9000,
"ratio": 15,
"timestamp": "2022-03-01 18:00:00",
},
]
}
return data
@app.route("/handle_my_position", methods=["POST"])
def handle_my_position():
"""处理持仓"""
data = json.loads(request.get_data())
print("根据接收到的数据进行一些操作:", data)
return {
"msg": "平仓成功!"
}
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, port=443)
这个示例是使用的flask,因为用到了跨域(具体的你不必了解),可以看到文件开头我们导入了CORS,所以要安装一下flask和flask_cors,首页折线图那里用到了pandas来筛选指定时间范围内的数据,所以也要安装pandas,使用pip命令就可以很方便地安装啦。示例项目跑起来之后你就可以看到各种数据了,因为数据是死的,所以图表这些都不是动态的,当你使用真实的一直在变化的数据时,图表就动态变化了,因此你要做的唯一的事情就是把数据替换成你自己的真实的数据,这里就涉及到了一些最基本的python数据处理的能力了。
示例项目的部署可以使用你自己的服务器,端口port=443可以改成你想要的端口,记得在服务器控制台的防火墙规则或者安全组中放行一下这个端口。对于没有服务器的朋友,可以使用pythonanywhere这个网站,在你注册一个账户后,它允许你部署一个web应用,其网址是:www.pythonanywhere.com/
使用pythonanywhere创建站点的时候python解释器的版本选择3.10,web框架选择flask,创建项目成功后会自动生成一个python文件,其路径是:/home/你的名字/mysite/flask_app.py,你只要把我们这个示例文件的代码复制粘贴过去,替换掉原有的内容,然后保存即可,保存完成后记得reload你的web应用程式。这个pythonanywhere的默认解释器环境里安装了flask和pandas这些模块,但是flask_cors没有,所以启动会报错Module not found: flask_cors,你只要在Bash命令窗口中pip install flask_cors然后重启一下web应用即可。
web应用部署好之后得在我们网站上绑定一下啊接口,登录以后进入首页,点击右上角头像那里的下拉框,点击接口配置,然后把接口都填写上,最后点击右上角的确认即可:
关于数据有几个值得注意的地方:
-
所有数据都必须按示例代码中的数据格式返回,否则会无法成功显示。
-
订单数据如果全部字段都有,则宽度不够,因此可以选择性地选取一些字段,字段多少按自己需求来,前端页面中是有
v-if这个vue指令的,因此存在的字段才会显示。 -
订单处理和持仓处理,当你点击
平多、取消等按钮时,其实它们做的事情都是一样的,就是把这个订单或者持仓的数据发送给你的web应用,按钮文字只是为了好看一点,你可以根据拿到的数据来做相应的处理,比如持仓数据,当你点击平多时,会给你的web应用发送这个订单的数据:{ "platform": "Stock", "symbol": "贵州茅台", "direction": "多头", "price": 1800, "quantity": 100, "profit": 9000, "ratio": 15, "timestamp": "2022-03-01 18:00:00", }然后你可以做一些处理,比如:
@app.route("/handle_my_position", methods=["POST"]) def handle_my_position(): """处理持仓""" data = json.loads(request.get_data()) print("根据接收到的数据进行一些操作:", data) if data["direction"] == "多头": symbol = data["symbol"] quantity = data["quantity"] print("发送请求去平这个单子,怎么平就是你自己的事啦") return { "msg": "平仓成功!" }
目前只有这个PC端的管理系统,后续可能会有手机端的站点,敬请期待!
有疑问或者需要定制可以加我微信:Gary-Hertel
Gary-Hertel
2022-11-03