策略发布
我们使用Json的方式创建策略,然后直接post到api上进行保存,保存后可以进行回测,两个策略,一个是大类资产配置,另一个是斜率动量/绝对动量加RSRS择时。
def build_slope():
task ={"symbols": ["513100.SH", "159934.SZ", "510880.SH", "159915.SZ"],
"features": ["roc(close,20)","slope_pair(high,low,18)"],
"feature_names": ["roc_20","rsrs_18"],
"rules_buy": [], "rules_sell": ["rsrs_18<0.7"],
"order_by":"roc_20"
}
from quant.services.backtest_utils import run_strategy
return run_strategy(task)
if __name__ == '__main__':
ratio, _ = build_slope()
print(ratio)
年化收益29.5%。
策略已经发布到线上平台:
今天使用Django的ModelForm来保存星球会员以及创建论坛bbs问答系统。
ModelForm是从Model里直接创建Form,这符合Django的设计理念,就是能固化下来的东西尽量复用。
官网中4.2的例子,就是博客发评论的例子,正好很合适咱们的场景。
https://docs.djangoproject.com/zh-hans/4.2/topics/forms/modelforms/
一般而言,CharField和IntField、FloatField等都会显示文本框。
如果模型字段设置了 choices ,那么表单字段的 widget 会被设置为 Select。——这一点就非常方便,如果前端要自己实现这个内容渲染,然后再读回控件的value,然后还需要把value再对应对choices,还是比较麻烦的。
咱们的星球会员绑定,需要会员名,会员到期日两个字段。
会员名就是普通文本CharField,这个比较简单。而DateField在Django默认是文本框。
头像使用ImageField可以上传图片。
pip install django-bootstrap-datepicker-plus
# File: forms.py
from bootstrap_datepicker_plus.widgets import DatePickerInput, TimePickerInput, DateTimePickerInput, MonthPickerInput, YearPickerInput
from django import forms
class EventForm(forms.ModelForm):
class Meta:
model = Event
fields = ["start_date", "start_time", "start_datetime", "start_month", "start_year"]
widgets = {
"start_date": DatePickerInput(),
"start_time": TimePickerInput(),
"start_datetime": DateTimePickerInput(),
"start_month": MonthPickerInput(),
"start_year": YearPickerInput(),
}
在Meta里使用wigets里覆盖date字段,使用DatePickInput()即可。
另外是文章Article(标题,正文,作者,发布时间,分类)和评论Comment(文章,评论人,评论时间)——文章使用Django-CKEditor。
Django的布署
咱们的AI量化平台,使用django + uvicorn + nginx + docker + docker-compose一起来布署。
FastApi使用的就是uvicorn,一般django使用gunicorn;但gunicorn不支持windows,使用起来也麻烦一点,因此,我们使用uvicorn。
uvicorn myproject.asgi:application --workers=3
本周的核心工作:网站2.0上线,带策略商城和论坛功能。
今日工作: 策略回测,列表页,详情页。
我们创建一个策略表现的model:
class StrategyPerformance(models.Model):
strategy = models.OneToOneField(StrategyInfo, on_delete=models.CASCADE, verbose_name='策略名称')
CAGR = models.FloatField(verbose_name='年化收益', default=-1)
sharpe = models.FloatField(verbose_name='夏普比率', default=-1)
mdd = models.FloatField(verbose_name='最大回撤率', default=-1)
def __str__(self):
return self.strategy.name
class Meta:
verbose_name = '策略表现'
verbose_name_plural = verbose_name
然后api里,任务成功回测完成后,写入表格中:
@api.post('/strategy/run/<task_id>')
def run_task(request, task_id: int):
strategy = StrategyInfo.objects.get(pk=task_id)
if not strategy:
return {'message': '策略:{}不存在'.format(task_id)}
dict_data = strategy.rule_data dict_data['name'] = strategy.name dict_data['desc'] = strategy.desc ratio, df = run_strategy(dict_data) se_task = ratio['market_value'] CAGR = se_task['年化收益'] sharpe = se_task['夏普比率'] mdd = se_task['最大回撤'] p = StrategyPerformance(strategy=strategy) p.CAGR = CAGR p.sharpe = sharpe p.mdd = mdd p.save() return {'message':'策略运行成功!'}
在admin的后台,就可以看到策略运行的结果:
接下来,我们就可以在“策略商城”里,把策略列表展现出来:
商城里展示效果如下:
然后我们来实现策略详情页。
数据准备,我们需要把回测结果保存在mongo数据库里:
df['date'] = df.index df['date'] = df['date'].apply(lambda x:str(x)) df['pk']=strategy.pk df['_id'] = str(task_id) + '_' + df['date'] mongo_utils.get_db()['strategy_quotes'].delete_many({'pk': strategy.pk}) mongo_utils.get_db()['strategy_quotes'].insert_many(df.to_dict(orient='records')) return {'message':'策略运行成功!'}
后台提供查询接口:
@api.get('/strategy_quotes/<pk>') def strategy_quotes(request, pk: int): items = mongo_utils.get_db()['strategy_quotes'].find({'pk': pk}, {'pk': 0, '_id': 0})
return {‘data’: list(items)}
数据很方便就查询出来了:
使用antd的g2来渲染数据:
{% load static %} <script src="{% static 'js/g2.min.js' %}"></script> <script> $.ajax({ // 后端程序的url地址 url: '/api/strategy_quotes/<pk>pk={{item.pk}}', // 也可以使用method,提交数据的方式,默认是'GET',常用的还有'POST' type: 'get', dataType: 'json', // 返回的数据格式,常用的有是'json','html',"jsonp" }) .done(function(resp) { // 请求成功以后的操作 console.log(resp); var chart = new G2.Chart({ container: 'quotes', autoFit: true, height: 300, padding: [30, 20, 70, 30] }); chart.data(resp['data']); chart.line().position('date*market_value').color('red') chart.line().position('date*基准').color('green') chart.render(); }) .fail(function(error) { // 请求失败以后的操作 console.log(error); }); </script>
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103493
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!