Skip to content

Commit 85e8659

Browse files
author
Zero
committed
update
1 parent 51d6005 commit 85e8659

File tree

7 files changed

+671
-14
lines changed

7 files changed

+671
-14
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
_obj
3+
.tmp
4+
_test
5+
__pycache__
6+
*.sqlite
7+
*.sqlite3
8+
*.pyc
9+
*.sh

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,10 @@ BotVS 对于 技术底层做出了强有力的支持,只需使用 BotVS 的
156156
return api('NewRobot', settings)
157157
```
158158
可以看到 代码中 settings 是创建 机器人的配置信息, appid 就是用来 标记用户的。
159+
160+
- 一个简单的交易中心
161+
162+
DEMO附带了一个简单的交易中心, 以帮助用户了解BotVS平台扩展API
163+
164+
https://dn-filebox.qbox.me/e9863cf66473b5a9ea974d0f4546cb7afe203414.png
159165

app.py

+53-12
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@
22

33
# 配置BotVS平台的AccessKey与SecretKey
44

5-
BOTVS_ACCESS_KEY = 'xxxxx'
6-
BOTVS_SECRET_KEY = 'yyyyy'
75

86
import os, time, urllib, md5, json, sqlite3, datetime
97
from flask import jsonify, request, Flask, render_template, redirect, url_for
108
from flask_bootstrap import WebCDN, Bootstrap
11-
from flask_wtf import Form
9+
from flask_wtf import FlaskForm
1210
from wtforms import StringField, PasswordField, BooleanField
1311
from wtforms.validators import InputRequired, Email, Length
1412
from flask_sqlalchemy import SQLAlchemy
1513
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
1614

15+
BOTVS_ACCESS_KEY = os.getenv('BOTVS_ACCESS_KEY', 'xxxxx')
16+
BOTVS_SECRET_KEY = os.getenv('BOTVS_SECRET_KEY', 'yyyyy')
17+
1718

1819
class cached(object):
1920
def __init__(self, *args, **kwargs):
@@ -49,7 +50,11 @@ def get_exchange_list():
4950
global exchanges_list
5051
if exchanges_list is None:
5152
# init exchanges
52-
exchanges_list = api('GetExchangeList', cache=True)['data']['result']['exchanges']
53+
#exchanges_list = api('GetExchangeList', cache=True)['data']['result']['exchanges']
54+
exchanges_list = [
55+
{u'website': u'https://www.binance.com/', u'name': u'\u5e01\u5b89', u'meta': u'[{"desc": "Access Key", "required": true, "type": "string", "name": "AccessKey", "label": "Access Key"}, {"encrypt": true, "name": "SecretKey", "required": true, "label": "Secret Key", "type": "password", "desc": "Secret Key"}]', u'eid': u'Binance', u'logo': u'binance.png', u'stocks': u'LTC_BTC,ETH_BTC,WTC_BTC', u'id': 0},
56+
{u'website': u'https://www.okex.com/', u'name': u'OKEX', u'meta': u'[{"desc": "Access Key", "required": true, "type": "string", "name": "AccessKey", "label": "Access Key"}, {"encrypt": true, "name": "SecretKey", "required": true, "label": "Secret Key", "type": "password", "desc": "Secret Key"}]', u'eid': u'OKEX', u'logo': u'okex.png', u'stocks': u'LTC_BTC,ETH_BTC,WTC_BTC', u'id': 1},
57+
]
5358
print ' * Initialize %d exchanges' % (len(exchanges_list), )
5459
return exchanges_list
5560

@@ -58,10 +63,12 @@ def get_default_stock(eid):
5863
if e['eid'] == eid:
5964
return e['stocks'].split(',')[0]
6065

61-
def plugin_run(exchanges, code):
66+
def plugin_run(exchanges, code, pair=None):
6267
settings = { "period": 60, "source": code, "exchanges": []}
6368
for e in exchanges:
64-
settings["exchanges"].append({"eid": e.eid, "pair": get_default_stock(e.eid), "meta" :{"AccessKey": e.accessKey, "SecretKey": e.secretKey}})
69+
if pair is None:
70+
piar = get_default_stock(e.eid)
71+
settings["exchanges"].append({"eid": e.eid, "pair": pair, "meta" :{"AccessKey": e.accessKey, "SecretKey": e.secretKey}})
6572
return api('PluginRun', settings)
6673

6774
def robot_run(robotId, appId, exchanges):
@@ -124,11 +131,11 @@ class Exchange(db.Model):
124131
def load_user(user_id):
125132
return User.query.get(int(user_id))
126133

127-
class LoginForm(Form):
134+
class LoginForm(FlaskForm):
128135
username = StringField(u'用户名', validators=[InputRequired(), Length(min=4, max=15)])
129136
password = PasswordField(u'密码', validators=[InputRequired(), Length(min=8, max=80)])
130137

131-
class RegisterForm(Form):
138+
class RegisterForm(FlaskForm):
132139
email = StringField(u'邮箱', validators=[InputRequired(), Email(message='无效的Email'), Length(max=50)])
133140
username = StringField(u'用户名', validators=[InputRequired(), Length(min=4, max=15)])
134141
password = PasswordField(u'密码', validators=[InputRequired(), Length(min=8, max=80)])
@@ -229,18 +236,52 @@ def assets():
229236
db.session.delete(Exchange.query.filter_by(user_id=current_user.id, id=request.args.get('pid', -1)).first())
230237
db.session.commit()
231238
return jsonify(results=True)
239+
platforms = Exchange.query.filter_by(user_id=current_user.id).all()
240+
return render_template('dashboard.html', current_user=current_user, platforms=platforms)
241+
242+
@app.route('/hub', methods=['GET', 'POST'])
243+
@login_required
244+
def hub():
245+
if request.method == "GET":
246+
action = request.args.get('action', None)
247+
symbol = request.args.get('symbol', None)
248+
if action is not None:
249+
action = action.lower().strip()
250+
if symbol is not None:
251+
symbol = symbol.split('.')[1]
252+
if action == "buy" or action == "sell":
253+
args = json.loads(request.args.get('args'))
254+
r = plugin_run([Exchange.query.filter_by(user_id=current_user.id, id=request.args.get('pid', -1)).first()], '''
255+
function main() {
256+
exchange.SetTimeout(2000);
257+
var pfn = '%s' == 'buy' ? exchange.Buy : exchange.Sell;
258+
return pfn(%f, %f);
259+
}
260+
''' % (action, args[0], args[1]), symbol)
261+
return jsonify(r)
262+
elif action == "cancel":
263+
args = json.loads(request.args.get('args'))
264+
r = plugin_run([Exchange.query.filter_by(user_id=current_user.id, id=request.args.get('pid', -1)).first()], '''
265+
function main() {
266+
exchange.SetTimeout(2000);
267+
return exchange.CancelOrder(%s)
268+
}
269+
''' % (args[0]), symbol)
270+
return jsonify(r)
232271
elif action == "balance":
233272
# 运行查询脚本(也可以定制实现任何想要的功能, 比如资产统计,一键平仓)
234273
r = plugin_run([Exchange.query.filter_by(user_id=current_user.id, id=request.args.get('pid', -1)).first()], '''
235274
function main() {
236275
exchange.SetTimeout(2000);
237-
return exchange.GetAccount();
276+
return [exchange.GetOrders(), exchange.GetAccount()];
238277
}
239-
''')
278+
''', symbol)
240279
return jsonify(r)
241280
platforms = Exchange.query.filter_by(user_id=current_user.id).all()
242-
return render_template('dashboard.html', current_user=current_user, platforms=platforms)
243-
281+
arr = []
282+
for ele in platforms:
283+
arr.append({'id': ele.id, 'eid': ele.eid, 'label': ele.label})
284+
return render_template('dashboard.html', current_user=current_user, platforms=json.dumps(arr))
244285
@app.route('/logout')
245286
@login_required
246287
def logout():

templates/assets.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
<td>{{ ele.date }}</td>
6262
<td width=160>
6363
<span class="btn btn-xs btn-danger" id="btn_del_{{ele.id}}" onclick="action('del', {{ele.id}})">删除</span>
64-
<span class="btn btn-xs btn-success" id="btn_balance_{{ele.id}}" onclick="action('balance', {{ele.id}})">余额</span>
64+
<a class="btn btn-xs btn-success" id="btn_balance_{{ele.id}}" href="{{ url_for('hub') }}">交易</a>
6565
</td>
6666
</tr>
6767
{% endfor %}

templates/dashboard.html

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,27 @@
99
<meta charset="utf-8">
1010
<meta http-equiv="X-UA-Compatible" content="IE=edge">
1111
<link rel="stylesheet" href="{{url_for('.static', filename='dashboard.css')}}">
12+
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
13+
<script src="http://apps.bdimg.com/libs/alertify.js/0.3.11/alertify.min.js"></script>
14+
<link rel="stylesheet" href="http://apps.bdimg.com/libs/alertify.js/0.3.11/alertify.default.css">
15+
<link rel="stylesheet" href="http://apps.bdimg.com/libs/alertify.js/0.3.11/alertify.core.css">
16+
{% if request.path == '/hub' %}
17+
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
18+
<script src="http://apps.bdimg.com/libs/angular.js/1.4.6/angular.min.js"></script>
19+
<script src="http://apps.bdimg.com/libs/moment/2.8.3/moment.js"></script>
20+
<script src="http://apps.bdimg.com/libs/underscore.js/1.7.0/underscore-min.js"></script>
21+
<script src="http://lib.sinaapp.com/js/highstock/2.0.1/highstock.js"></script>
22+
{% endif %}
23+
1224
{% endblock %}
1325
{% block content %}
1426
{% include "nav.html" %}
1527
<div class="container-fluid">
1628
<div class="row">
1729
<div class="col-sm-3 col-md-2 sidebar">
1830
<ul class="nav nav-sidebar">
19-
<li class="{% if request.path == '/dashboard' %}active{%else%}inactive{% endif %}"><a href="/dashboard"><span class="glyphicon glyphicon-knight" style="width:20px"></span>投资策略</a></li>
31+
<li class="{% if request.path == '/dashboard' %}active{%else%}inactive{% endif %}"><a href="/dashboard"><span class="glyphicon glyphicon-knight" style="width:20px"></span>投资策略</a></li>
32+
<li class="{% if request.path == '/hub' %}active{%else%}inactive{% endif %}"><a href="/hub"><span class="glyphicon glyphicon-flash" style="width:20px"></span>交易中心</a></li>
2033
<li class="{% if request.path == '/assets' %}active{%else%}inactive{% endif %}"><a href="/assets"><span class="glyphicon glyphicon-lock" style="width:20px"></span>资产状态</a></li>
2134
<li class="{% if request.path == '/exchanges' %}active{%else%}inactive{% endif %}"><a href="/exchanges"><span class="glyphicon glyphicon-magnet" style="width:20px"></span>添加资产</a></li>
2235
</ul>

templates/exchanges.html

100644100755
File mode changed.

0 commit comments

Comments
 (0)