This commit is contained in:
Zero
2016-06-07 14:37:18 +08:00
parent 41e89c0154
commit cca84d09d0
7 changed files with 575 additions and 5 deletions
+6 -4
View File
@@ -4,10 +4,15 @@
> 开源策略列表
- [商品期货交易类库(增加下限价单功能)](https://www.botvs.com/strategy/14198)
- [从回测数据获取K线 (商品期货版)](https://www.botvs.com/strategy/15498)
- [图表模板](https://www.botvs.com/strategy/15524)
- [时间转换模板](https://www.botvs.com/strategy/14517)
- [非常简单的策略,但是很有效](https://www.botvs.com/strategy/15085)
- [定时测试微信消息推送](https://www.botvs.com/strategy/15098)
- [单独计算收益(代码来自zero)](https://www.botvs.com/strategy/1084)
- [差价监控](https://www.botvs.com/strategy/1340)
- [MACD 双向 滑动止损](https://www.botvs.com/strategy/12822)
- [时间转换模板](https://www.botvs.com/strategy/14517)
- [10行人品策略](https://www.botvs.com/strategy/14436)
- [商品期货主力合约过滤](https://www.botvs.com/strategy/9837)
- [从第三方网站获取K线 (0427更新)](https://www.botvs.com/strategy/12977)
@@ -27,12 +32,9 @@
- [自定义K线周期转换](https://www.botvs.com/strategy/11216)
- [模板库使用例子](https://www.botvs.com/strategy/10991)
- [价值0.418](https://www.botvs.com/strategy/10744)
- [均线](https://www.botvs.com/strategy/10023)
- [价值比例法](https://www.botvs.com/strategy/9784)
- [传统期货差价监控 (CTP)](https://www.botvs.com/strategy/5379)
- [期货做市高频交易策略 兼容OK/VC/796](https://www.botvs.com/strategy/1484)
- [融资融币统计](https://www.botvs.com/strategy/8954)
- [**********价值平均定投策略**********](https://www.botvs.com/strategy/8602)
- [【Demo】如何利用“策略交互“动态调整策略参数](https://www.botvs.com/strategy/8379)
- [【Demo】速度测试 websocket vs rest](https://www.botvs.com/strategy/7547)
- [记录净资产变动情况2.0](https://www.botvs.com/strategy/8916)
@@ -0,0 +1,58 @@
/*
策略出处: https://www.botvs.com/strategy/15498
策略名称: 从回测数据获取K线 (商品期货版)
策略作者: 数·狂
策略描述:
如果在策略开始时必须获取足够多的K线,使用本模板则可从BotVS的回测数据中直接获得平台的历史K线数据。
注意:
仅适用于实盘交易。
作者不保证第三方数据准确性和程序正确性,仅供学习参考。
*/
$.BTRecords = function(instrument, timeframe, size, includeLastBar) {
var info;
var record = [];
if (!size) size = 1;
if (!timeframe) timeframe = 1;
var fsize = size;
var now = new Date();
var to = Math.floor(now / 1000 / (timeframe * 60)) * (timeframe * 60);
var from = to - fsize * timeframe * 60;
do {
try {
info = JSON.parse(HttpQuery('https://www.botvs.com/chart/history?detail=true&symbol=' + instrument + '&resolution=' + timeframe + '&from=' + from + '&to=' + to));
if (info && info.records) {
info = info.records;
} else {
Log("获取K线时发生错误: 网络错误");
return null;
}
} catch (e) {
Log("获取K线时发生错误: 不完整的JSON数据");
return null;
}
fsize = fsize * 2;
from = to - fsize * timeframe * 60;
} while (info.length < size + (!includeLastBar));
for (var i = info.length - size - (!includeLastBar); i < info.length - (!includeLastBar); i++) {
record.push({
"Time": info[i][0]*1000,
"Open": info[i][1],
"High": info[i][2],
"Low": info[i][3],
"Close": info[i][4],
"Volume": info[i][5]
});
}
return record;
};
function main() {
Log(exchange.GetName());
var rec = $.BTRecords('rb1610', 5, 100); // 获取螺纹钢1610的5分钟K线, 100条, 不含最后一条Bar
if (rec) Log(rec.length, rec[rec.length - 1]);
rec = $.BTRecords('i1609', 60, 100, true); // 获取铁矿石1609的1小时K线, 100条, 含最后一条Bar
if (rec) Log(rec.length, rec[rec.length - 1]);
}
@@ -0,0 +1,297 @@
/*
策略出处: https://www.botvs.com/strategy/14198
策略名称: 商品期货交易类库(增加下限价单功能)
策略作者: edwardgyw
策略描述:
在原zero提供版本基础上,增加了下限价单和平限价单的功能,方便埋单
增加了判断当前是否是交易时段的功能,同时提供自定义节假日的功能
参数 默认值 描述
------------ ------- ----------
Interval 500 失败重试间隔(毫秒)
SlidePrice false 下单滑价(元)
nightType true 商品夜盘情况
holidaysList 5.1,5.2 节假日情况
*/
function GetPosition(e, contractType, direction) {
var allCost = 0;
var allAmount = 0;
var allProfit = 0;
var allFrozen = 0;
var posMargin = 0;
var positions = _C(e.GetPosition);
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType == contractType &&
(((positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) && direction == PD_LONG) || ((positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD) && direction == PD_SHORT))
) {
posMargin = positions[i].MarginLevel;
allCost += (positions[i].Price * positions[i].Amount);
allAmount += positions[i].Amount;
allProfit += positions[i].Profit;
allFrozen += positions[i].FrozenAmount;
}
}
if (allAmount === 0) {
return null;
}
return {
MarginLevel: posMargin,
FrozenAmount: allFrozen,
Price: _N(allCost / allAmount),
Amount: allAmount,
Profit: allProfit,
Type: direction,
ContractType: contractType
};
}
function Open(e, contractType, direction, opAmount, price) {
var initPosition = GetPosition(e, contractType, direction);
var isFirst = true;
var initAmount = initPosition ? initPosition.Amount : 0;
var positionNow = initPosition;
while (true) {
var needOpen = opAmount;
if (isFirst) {
isFirst = false;
} else {
positionNow = GetPosition(e, contractType, direction);
if (positionNow) {
needOpen = opAmount - (positionNow.Amount - initAmount);
}
}
var insDetail = _C(e.SetContractType, contractType);
//Log("初始持仓", initAmount, "当前持仓", positionNow, "需要加仓", needOpen);
if (needOpen < insDetail.MinLimitOrderVolume) {
break;
}
var depth = _C(e.GetDepth);
var pr = price;
if (!price) pr = direction == PD_LONG ? depth.Asks[0].Price : depth.Bids[0].Price;
var amount = Math.min(insDetail.MaxLimitOrderVolume, needOpen);
e.SetDirection(direction == PD_LONG ? "buy" : "sell");
var orderId;
if (direction == PD_LONG) {
orderId = e.Buy(pr + SlidePrice, Math.min(amount, depth.Asks[0].Amount), contractType, 'Ask', depth);
} else {
orderId = e.Sell(pr - SlidePrice, Math.min(amount, depth.Bids[0].Amount), contractType, 'Bid', depth);
}
// CancelPendingOrders
while (true) {
Sleep(Interval);
var orders = _C(e.GetOrders);
if (orders.length === 0) {
break;
}
for (var j = 0; j < orders.length; j++) {
e.CancelOrder(orders[j].Id);
if (j < (orders.length - 1)) {
Sleep(Interval);
}
}
}
}
var ret = {
price: 0,
amount: 0,
position: positionNow
};
if (!positionNow) {
return ret;
}
if (!initPosition) {
ret.price = positionNow.Price;
ret.amount = positionNow.Amount;
} else {
ret.amount = positionNow.Amount - initPosition.Amount;
ret.price = _N(((positionNow.Price * positionNow.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount);
}
return ret;
}
function Cover(e, contractType, price) {
var insDetail = _C(e.SetContractType, contractType);
while (true) {
var n = 0;
var positions = _C(e.GetPosition);
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType != contractType) {
continue;
}
while (positions[i].FrozenAmount !== 0) {
var orders = _C(e.GetOrders);
if (orders.length === 0) {
break;
}
for (var j = 0; j < orders.length; j++) {
e.CancelOrder(orders[j].Id);
if (j < (orders.length - 1)) {
Sleep(Interval);
}
}
positions = _C(e.GetPosition);
}
var amount = Math.min(insDetail.MaxLimitOrderVolume, positions[i].Amount);
var depth;
if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {
depth = _C(e.GetDepth);
var pr = price;
if (!price) pr = depth.Bids[0].Price;
e.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");
e.Sell(pr - SlidePrice, Math.min(amount, depth.Bids[0].Amount), contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
n++;
} else if (positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD) {
depth = _C(e.GetDepth);
var pr = price;
if (!price) pr = depth.Asks[0].Price;
e.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
e.Buy(pr + SlidePrice, Math.min(amount, depth.Asks[0].Amount), contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
n++;
}
}
if (n === 0 || price) {
break;
}
while (true) {
Sleep(Interval);
var orders = _C(e.GetOrders);
if (orders.length === 0) {
break;
}
for (var j = 0; j < orders.length; j++) {
e.CancelOrder(orders[j].Id);
if (j < (orders.length - 1)) {
Sleep(Interval);
}
}
}
}
}
var PositionManager = (function() {
function PositionManager(e) {
if (typeof(e) === 'undefined') {
e = exchange;
}
if (e.GetName() !== 'Futures_CTP') {
throw 'Only support CTP';
}
this.e = e;
this.account = null;
}
PositionManager.prototype.GetAccount = function() {
return _C(this.e.GetAccount);
};
PositionManager.prototype.OpenLong = function(contractType, shares, price) {
if (!this.account) {
this.account = _C(exchange.GetAccount);
}
return Open(this.e, contractType, PD_LONG, shares, price, price);
};
PositionManager.prototype.OpenShort = function(contractType, shares, price) {
if (!this.account) {
this.account = _C(exchange.GetAccount);
}
return Open(this.e, contractType, PD_SHORT, shares, price);
};
PositionManager.prototype.Cover = function(contractType, price) {
if (!this.account) {
this.account = _C(exchange.GetAccount);
}
return Cover(this.e, contractType, price);
};
PositionManager.prototype.Profit = function(contractType) {
var accountNow = _C(this.e.GetAccount);
return _N(accountNow.Balance - this.account.Balance);
};
return PositionManager;
})();
$.NewPositionManager = function(e) {
return new PositionManager(e);
};
function getHolidays(holidaysList) {
if (!holidaysList) return {
'mon': [],
'day': []
};
var x = holidaysList.split(',');
var t = {
'mon': [],
'day': []
};
for (var i = 0; i < x.length; i++) {
var m = x[i].split('.');
t.mon.push(m[0]);
t.day.push(m[1]);
}
return t;
}
$.judgeTrading = function() {
var now = new Date();
var day = now.getDay();
var mon = now.getMonth() + 1;
var min = now.getMinutes();
var date = now.getDate();
var hours = now.getHours();
var isHolidays = false;
var holidays = getHolidays(holidaysList);
//Log(holidays.mon.length);
if (holidays) {
for (var i = 0; i < holidays.mon.length; i++) {
if (holidays.mon[i] == mon && holidays.day[i] == date) {
isHolidays = true;
break;
}
}
}
if (day == 0 || day == 6 || isHolidays) return false;
else if ((hours >= 9 && hours <= 11) || (hours >= 13 && hours < 15)) {
if (hours == 11 && min >= 30) return false;
else if (hours == 13 && min < 30) return false;
else if ((hours == 10 && min >= 15) && (hours == 10 && min < 30)) return false;
else return true;
} else if (nightType == 1 && hours >= 21 && hours < 23) return true;
else if (nightType == 2 && ((hours >= 21 && hours < 24) || (hours >= 0 && hours < 1 && day !== 1))) return true;
//else if(nightType!==1&&nightType!==2) return true;
else return false;
};
//未成功登陆前要多次尝试login,所以写了一个准备交易的函数,可以放到main函数开头
$.ready4ctp = function(contractType) {
var insDetail;
var retry = 0;
while (!(insDetail = exchange.SetContractType(contractType)) && retry < 20) {
Sleep(2000);
retry++;
}
if (insDetail) Log("合约", insDetail.InstrumentName, "一手", insDetail.VolumeMultiple, "份, 最大下单量", insDetail.MaxLimitOrderVolume, "保证金率:", insDetail.LongMarginRatio, "交割日期", insDetail.StartDelivDate);
else throw ('连接超时,请检查账号');
return insDetail;
};
function main() {
$.ready4ctp('MA609');
var isTrading = $.judgeTrading();
Log('当前正在交易?:'+isTrading);
var p = $.NewPositionManager();
p.OpenShort("MA609", 1, 1000);
Sleep(60000 * 10);
p.Cover("MA609", 1000);
p.Cover('MA609');
LogProfit(p.Profit());
}
+118
View File
@@ -0,0 +1,118 @@
/*
策略出处: https://www.botvs.com/strategy/15524
策略名称: 图表模板
策略作者: 小小梦
策略描述:
图表模板
参数 默认值 描述
-------------- ----- ------
indicatorsName 指标轴1 指标轴
indicators_1 指标1 指标1
indicators_2 指标2 指标2
Interval 500 间隔(毫秒)
*/
/*
这个是一个图表模板,详细用法见广场帖子。
*/
//图表
var ChartObj = {//画图
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},
chart: { zoomType:'x',panning:true },//图表类型
title: { text: title}, //标题
rangeSelector: {
buttons: [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
selected: 0,
inputEnabled: false
},
subtitle: {text: subtitle},//副标题
xAxis:{type: 'datetime'},
yAxis: [{
title: {text: 'K线'},//标题
style: {color: '#4572A7'},//样式
opposite: false //生成右边Y轴
},
{
title:{text: indicatorsName},
opposite: true //生成右边Y轴 ceshi
}
],
series: [//系列
{type:'candlestick',yAxis:0,name:'K',id:'KLine',data:[]},
{type:'flags',onSeries:'KLine',data:[]},
{name:indicators_1,type:'spline',yAxis:1,data:[]},
{name:indicators_2,type:'spline',yAxis:1,data:[]}
]
};
var chart = Chart(ChartObj);
var isFirst = true;
var preRecordTime = 0;
var title = exchange.GetName();
var subtitle = indicators_1+"、"+indicators_2+"指标走势";
function Draw(records){
var strState = "";
var fcolor = "";
var msg = "";
while(!records || records.length < 5){
records = exchange.GetRecords();
LogStatus("获取K线中...records.length:",records === null ? "records is null" : records.length);
Sleep(Interval);
}
if(isFirst === true){
chart.reset();
isFirst = false;
preRecordTime = records[records.length - 1].Time;
}
if(preRecordTime === records[records.length - 1].Time){
chart.add([0,[records[records.length - 1].Time,records[records.length - 1].Open,records[records.length - 1].High,records[records.length - 1].Low,records[records.length - 1].Close ],-1]);
}else{
//更新前一柱
chart.add([0,[records[records.length - 2].Time,records[records.length - 2].Open,records[records.length - 2].High,records[records.length - 2].Low,records[records.length - 2].Close ],-1]);
chart.add([0,[records[records.length - 1].Time,records[records.length - 1].Open,records[records.length - 1].High,records[records.length - 1].Low,records[records.length - 1].Close ]]);
preRecordTime = records[records.length - 1].Time;
}
chart.update(ChartObj);
chart.reset(500);
}
function SignOP(time,price,amount,state){
var msg = "";
msg = "均价:"+price+"币数:"+amount;
switch(state){
case 1:strState = "开多仓";fcolor = "red";break;
case 2:strState = "开空仓";fcolor = "green";break;
case 0:strState = "平仓";fcolor = "blue";break;
}
chart.add(1, {x:time, color: fcolor , shape: 'flag', title: strState, text: msg});
}
$.SignOP = function(time,price,amount,state){
if(arguments.length < 4){
Log("SignOP 函数 必须传入4个参数 : time、price、amount、state");
return;
}
SignOP(time,price,amount,state);
};
$.Draw = function(records){
Draw(records);
};
//ceshi
function main(){
var i = 0;
var records = exchange.GetRecords();
while(i < 50000){
if(i===2000){
//Sleep(60*60*1000);
SignOP((new Date()).getTime(),2900,1,1);
}
Draw(records);
Sleep(20000);
records = exchange.GetRecords();
i++;
}
}
+25
View File
@@ -0,0 +1,25 @@
/*
策略出处: https://www.botvs.com/strategy/15098
策略名称: 定时测试微信消息推送
策略作者: 小小梦
策略描述:
定时测试微信消息推送 范例~抛砖引玉,方便用户参考学习。
*/
function main(){
var initTime = (new Date()).getTime() ;
Log("程序起始时间:",$.getTimeByNormal(initTime) );
var preDif = 0;
var str = "";
while(true){
var nowTime = (new Date()).getTime();
if( Math.floor((nowTime - initTime) / (1000*60*10) ) !== preDif ){
str = $.getTimeByNormal(nowTime);
Log("从程序开始执行,已过10分钟!提醒。"+"--现在时间:"+str+"推送微信@" );
preDif = Math.floor((nowTime - initTime) / (1000*60*10) ) ;
}
Sleep(2000);
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ function getTimeByNormal(time){
//测试
function main() {
var time1 = $.getTimeByNormal( new Date() );
var time1 = $.getTimeByNormal( 1463308260000 );
Log("当前时间time1:",time1);
Sleep(1000 * 60);
var time3 = (new Date()).getTime();
@@ -0,0 +1,70 @@
/*
策略出处: https://www.botvs.com/strategy/15085
策略名称: 非常简单的策略,但是很有效
策略作者: jiebang
策略描述:
"Talk is cheap. Show me the code"
注: ` 策略使用了交易模板类库`
`希望新手从此策略入门, 一步步学习编写策略, 并体验到模拟与真实环境对交易系统的影响`
https://dn-filebox.qbox.me/fb4d0c7d773ca83e9d0230927705d419dc0bbeaa.png
参数 默认值 描述
------------- ----- -------
FastPeriod 5 入市快线周期
SlowPeriod 30 入市慢线周期
EnterPeriod 2 入市观察期
PositionRatio true 仓位比例
Interval 10 轮询周期(秒)
SlidePrice 0.01 滑动值
*/
function main()
{
var STATE_IDLE = -1;
var state = STATE_IDLE;
var initAccount = $.GetAccount();
var price = 0;
Log(initAccount);
while (true)
{
ticker = exchange.GetTicker();
var nowAccount = $.GetAccount();
var n = $.Cross(FastPeriod, SlowPeriod);
if (Math.abs(n) >= EnterPeriod && Math.abs(n) < EnterPeriod +1 )
{
if (n > 0)
{
price = ticker.Sell;
var opAmount = parseFloat((nowAccount.Balance * PositionRatio/(ticker.Sell+SlidePrice)).toFixed(3));
}
else
{
price = ticker.Buy;
var opAmount = nowAccount.Stocks;
}
if (opAmount> exchange.GetMinStock())
{
var obj = n > 0 ? exchange.Buy(price, opAmount) : $.Sell(price, opAmount);
if (obj)
{
opAmount = obj.amount;
// state = n > 0 ? PD_LONG : PD_SHORT;
Log("开仓详情", obj, "交叉周期", n, "币:", nowAccount.Stocks);
LogProfit(nowAccount.Balance + nowAccount.Stocks * ticker.Last , '钱');
}
/*else
{
continue;
} */
}
}
Sleep(Interval*1000);
}
}