update
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/37678
|
||||
策略名称: Convert_Record_Cycle
|
||||
策略作者: jxc6698
|
||||
策略描述:
|
||||
|
||||
# 得到指定周期的蜡烛图 线数据
|
||||
|
||||
如有BUG ,问题 欢迎留言
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
---------------- ------------ -------
|
||||
UI_NewCycleForMS 1000*60*60*2 合成周期毫秒数
|
||||
*/
|
||||
|
||||
/**
|
||||
* author: jcx
|
||||
* date: 3/10/2017
|
||||
*/
|
||||
/**
|
||||
* 修改自小小梦的"转换任意K线周期" 模板,支持设置任意的周期大小,支持输入ticker
|
||||
* 时间设置必须是当前提供的 records[]周期的整数倍才有意义(在程序中没有检查)
|
||||
*
|
||||
*
|
||||
* 考虑到在getrecords() 返回的最后一个数据可能会改变.
|
||||
* 1. 可以在main函数中循环 从0 到 < length-1
|
||||
* 2. 或者是当前处理方法,在AddKLine方法中,使用timeAfOrEq(),允许最后一个时段的值更新
|
||||
* (隐含要求添加kline records 按照时间顺序)
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// K线周期合成 扩展为 根据基础K线 合成 为任意周期。
|
||||
var cloneObj = function(obj) { // 深拷贝 对象函数
|
||||
var str, newobj = obj.constructor === Array ? [] : {};
|
||||
if (typeof obj !== 'object') {
|
||||
return;
|
||||
} else if (JSON) {
|
||||
str = JSON.stringify(obj); //系列化对象
|
||||
newobj = JSON.parse(str); //还原
|
||||
} else {
|
||||
for (var i in obj) {
|
||||
newobj[i] = typeof obj[i] === 'object' ?
|
||||
cloneObj(obj[i]) : obj[i];
|
||||
}
|
||||
}
|
||||
return newobj;
|
||||
};
|
||||
|
||||
/**
|
||||
* NeWCycleForMS: 新的周期
|
||||
* n : 每次返回的 蜡烛records数组大小
|
||||
*/
|
||||
var DefaultN = 10
|
||||
function AssembleRecords(NewCycleForMS, n) {
|
||||
var self = {}
|
||||
self.NewCycleForMS = NewCycleForMS;
|
||||
self.curBars = [] // 用来存储 最近 n 个蜡烛对象
|
||||
n = parseInt(n) // 存储每次返回的蜡烛数量
|
||||
if (n*1 === n)
|
||||
self.n = n
|
||||
else
|
||||
self.n = DefaultN
|
||||
// 临时变量
|
||||
self.tmp = {lasttime: 0}
|
||||
|
||||
self.timeAf = function (time1, time2) {
|
||||
return time1 < time2
|
||||
}
|
||||
self.timeAfOrEq = function (time1, time2) {
|
||||
return time1 <= time2
|
||||
}
|
||||
self.inSameKLine = function (time1, time2) {
|
||||
if (parseInt(time1/self.NewCycleForMS) ===
|
||||
parseInt(time2/self.NewCycleForMS)) {
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
}
|
||||
self.getKlineStartTime = function (time) {
|
||||
return time - time%self.NewCycleForMS
|
||||
}
|
||||
self.newBarObj = function (time, v) {
|
||||
var value = 0;
|
||||
value = v
|
||||
return { // 定义一个 K线柱结构
|
||||
Time: time,
|
||||
Open: value,
|
||||
High: value,
|
||||
Low: value,
|
||||
Close: value,
|
||||
Volume: 0
|
||||
}
|
||||
}
|
||||
self.updateNewBar = function(time, defaultvalue) {
|
||||
var barobj;
|
||||
if (self.curBars.length == 0) {
|
||||
barobj = self.newBarObj(self.getKlineStartTime(time),
|
||||
defaultvalue)
|
||||
self.curBars.push(barobj)
|
||||
} else if(!self.inSameKLine(self.curBars[self.curBars.length-1].Time,
|
||||
time) ) {
|
||||
barobj = self.newBarObj(self.getKlineStartTime(time),
|
||||
defaultvalue)
|
||||
self.curBars.push(barobj)
|
||||
}
|
||||
|
||||
if (self.curBars.length > n+2) {
|
||||
self.curBars.shift()
|
||||
}
|
||||
return self.curBars[self.curBars.length-1];
|
||||
}
|
||||
self.AddTicker = function (ticker) {
|
||||
var barobj;
|
||||
// ticker should passed as time order
|
||||
barobj = self.updateNewBar(ticker.Time, ticker.Last);
|
||||
|
||||
if (!self.timeAfOrEq(self.barobj[self.barobj.length-1].Time,
|
||||
cker.Time)) {
|
||||
return;
|
||||
}
|
||||
if (barobj.High < ticker.High)
|
||||
barobj.High = ticker.High
|
||||
if (barobj.Low > ticker.Low)
|
||||
barobj.Low = ticker.Low
|
||||
barobj.Close = ticker.Last
|
||||
// barobj.Volume += ticker.Volume
|
||||
}
|
||||
self.AddKLine = function (klinerecord) {
|
||||
var barobj;
|
||||
|
||||
// must use <=, when stepping into new record, last record may change
|
||||
if (!self.timeAfOrEq(self.tmp.lasttime,
|
||||
klinerecord.Time)) {
|
||||
return
|
||||
}
|
||||
barobj = self.updateNewBar(klinerecord.Time, klinerecord.Open)
|
||||
self.tmp.lasttime = klinerecord.Time
|
||||
|
||||
if (barobj.High < klinerecord.High) {
|
||||
barobj.High = klinerecord.High
|
||||
}
|
||||
if (barobj.Low > klinerecord.Low)
|
||||
barobj.Low = klinerecord.Low
|
||||
barobj.Close = klinerecord.Close
|
||||
barobj.Volume += klinerecord.Volumn
|
||||
}
|
||||
self.GetKline = function () {
|
||||
var len = self.curBars.length;
|
||||
return self.curBars.slice(len-self.n);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// 测试代码
|
||||
function main() {
|
||||
var records = exchange.GetRecords();
|
||||
while (!records || records.length < 24) {
|
||||
records = exchange.GetRecords();
|
||||
}
|
||||
|
||||
// 处理界面参数, 如果写到自己的策略里面 可以参考下
|
||||
|
||||
var Num_UI_NewCycleForMS = 1;
|
||||
var arrayNum = UI_NewCycleForMS.split("*");
|
||||
for(var indexNum = 0 ; indexNum < arrayNum.length ; indexNum++){
|
||||
Num_UI_NewCycleForMS = Num_UI_NewCycleForMS * Number(arrayNum[indexNum]);
|
||||
}
|
||||
Log("自定义周期毫秒时间为:", Num_UI_NewCycleForMS);
|
||||
|
||||
// 第一个参数是 基础K线, 第二个参数是 要转换的周期的 毫秒数, 1000 * 60 * 20 就是 转换为 20分钟
|
||||
obj = AssembleRecords(Num_UI_NewCycleForMS, 5);
|
||||
|
||||
|
||||
|
||||
while(true){
|
||||
records = _C(exchange.GetRecords);
|
||||
|
||||
for (var i=0;i<records.length;i++) {
|
||||
obj.AddKLine(records[i])
|
||||
}
|
||||
|
||||
newrecords = obj.GetKline()
|
||||
$.PlotRecords(newrecords, 'BTC');
|
||||
|
||||
// throw "stop"; // ceshi
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/21583
|
||||
策略名称: Dual Thrust (现货版)
|
||||
策略作者: 小小梦
|
||||
策略描述:
|
||||
|
||||
Dual Thrust 策略包含完整的图表显示, 图表动态更新,模板引用等功能, 可做学习模板使用.
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
------------ ----- ----------
|
||||
NPeriod 4 计算周期
|
||||
Ks 0.5 上轨系数
|
||||
Kx 0.5 下轨系数
|
||||
AmountOP true 开仓量
|
||||
Interval 2000 重试间隔(毫秒)
|
||||
LoopInterval 3 轮询间隔(秒)
|
||||
PeriodShow 500 图表最大显示K线柱数
|
||||
maxProfit 0.5 止盈值
|
||||
*/
|
||||
|
||||
var ChartCfg = {
|
||||
__isStock: true,
|
||||
title: {
|
||||
text: 'Dual Thrust 上下轨图'
|
||||
},
|
||||
yAxis: {
|
||||
plotLines: [{
|
||||
value: 0,
|
||||
color: 'red',
|
||||
width: 2,
|
||||
label: {
|
||||
text: '上轨',
|
||||
align: 'center'
|
||||
},
|
||||
}, {
|
||||
value: 0,
|
||||
color: 'green',
|
||||
width: 2,
|
||||
label: {
|
||||
text: '下轨',
|
||||
align: 'center'
|
||||
},
|
||||
}]
|
||||
},
|
||||
series: [{
|
||||
type: 'candlestick',
|
||||
name: '当前周期',
|
||||
id: 'primary',
|
||||
data: []
|
||||
}, {
|
||||
type: 'flags',
|
||||
onSeries: 'primary',
|
||||
data: [],
|
||||
}]
|
||||
};
|
||||
|
||||
var STATE_IDLE = 0;
|
||||
var STATE_LONG = 1;
|
||||
var STATE_SHORT = 2;
|
||||
var State = STATE_IDLE;
|
||||
|
||||
var LastBarTime = 0;
|
||||
var UpTrack = 0;
|
||||
var BottomTrack = 0;
|
||||
var chart = null;
|
||||
var InitAccount = null;
|
||||
var Counter = {
|
||||
w: 0,
|
||||
l: 0
|
||||
};
|
||||
|
||||
function _N(v) {
|
||||
return Decimal(v).toSD(4, 1).toNumber();
|
||||
}
|
||||
|
||||
function CancelPendingOrders() {
|
||||
while (true) {
|
||||
var orders = exchange.GetOrders();
|
||||
for (var i = 0; i < orders.length; i++) {
|
||||
exchange.CancelOrder(orders[i].Id);
|
||||
Sleep(Interval);
|
||||
}
|
||||
if (orders.length === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isTrade_OC = false;
|
||||
function onTick(exchange) {
|
||||
var records = exchange.GetRecords();
|
||||
if (!records || records.length <= NPeriod) {
|
||||
return;
|
||||
}
|
||||
var Bar = records[records.length - 1];
|
||||
if (LastBarTime !== Bar.Time) {
|
||||
isTrade_OC = false;
|
||||
var HH = TA.Highest(records, NPeriod, 'High');
|
||||
var HC = TA.Highest(records, NPeriod, 'Close');
|
||||
var LL = TA.Lowest(records, NPeriod, 'Low');
|
||||
var LC = TA.Lowest(records, NPeriod, 'Close');
|
||||
|
||||
var Range = Math.max(HH - LC, HC - LL);
|
||||
|
||||
UpTrack = _N(Bar.Open + (Ks * Range));
|
||||
DownTrack = _N(Bar.Open - (Kx * Range));
|
||||
if (LastBarTime > 0) {
|
||||
var PreBar = records[records.length - 2];
|
||||
chart.add(0, [PreBar.Time, PreBar.Open, PreBar.High, PreBar.Low, PreBar.Close], -1);
|
||||
} else {
|
||||
for (var i = Math.min(records.length, NPeriod * 3); i > 1; i--) {
|
||||
var b = records[records.length - i];
|
||||
chart.add(0, [b.Time, b.Open, b.High, b.Low, b.Close]);
|
||||
}
|
||||
}
|
||||
chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close]);
|
||||
ChartCfg.yAxis.plotLines[0].value = UpTrack;
|
||||
ChartCfg.yAxis.plotLines[1].value = DownTrack;
|
||||
ChartCfg.subtitle = {
|
||||
text: '上轨: ' + UpTrack + ' 下轨: ' + DownTrack
|
||||
};
|
||||
chart.update(ChartCfg);
|
||||
chart.reset(PeriodShow);
|
||||
|
||||
LastBarTime = Bar.Time;
|
||||
} else {
|
||||
chart.add(0, [Bar.Time, Bar.Open, Bar.High, Bar.Low, Bar.Close], -1);
|
||||
}
|
||||
|
||||
LogStatus("Price:", Bar.Close, "Up:", UpTrack, "Down:", DownTrack, "Wins: ", Counter.w, "Losses:", Counter.l, "Date:", new Date(),"\n",NowPositionInfo);
|
||||
var msg;
|
||||
var fcolor = null;
|
||||
var ftitle = "";
|
||||
if(isTrade_OC === true){
|
||||
return;
|
||||
}
|
||||
|
||||
if (State === STATE_IDLE || State === STATE_SHORT) {
|
||||
if (Bar.Close >= UpTrack) {
|
||||
msg = '做多 触发价: ' + Bar.Close + ' 上轨:' + UpTrack;
|
||||
Log(msg);
|
||||
buyInfo = $.Buy(AmountOP); //Trade(State, STATE_LONG);
|
||||
State = STATE_LONG;
|
||||
Log("buyInfo:",buyInfo);
|
||||
if(buyInfo === null){
|
||||
return;
|
||||
}
|
||||
//chart.add(1, {x:Bar.Time, color: 'red', shape: 'flag', title: '多', text: msg});
|
||||
if(NowPositionInfo.direction === NONE){
|
||||
NowPositionInfo.direction = LONG;
|
||||
fcolor = 'red';
|
||||
ftitle = '多';
|
||||
}else if(NowPositionInfo.direction === SHORT){
|
||||
State = STATE_IDLE;
|
||||
NowPositionInfo.direction = NONE;
|
||||
Calculate();
|
||||
//Profit = (nowAccount.Stocks - beginAccount.Stocks) * (NowPositionInfo.direction === SHORT?nowDepth.Bids[0].Price : nowDepth.Asks[0].Price) + (beginAccount.Balance - nowAccount.Balance); //总盈亏
|
||||
InitAccount = _C(exchange.GetAccount);
|
||||
LogProfit(Profit,InitAccount);
|
||||
fcolor = 'blue';
|
||||
ftitle = '平';
|
||||
isTrade_OC = true;//当前bar 已经交易
|
||||
}
|
||||
chart.add(1, {x:Bar.Time, color: fcolor, shape: 'flag', title: ftitle, text: msg});
|
||||
}
|
||||
}
|
||||
|
||||
if (State === STATE_IDLE || State === STATE_LONG) {
|
||||
if (Bar.Close <= DownTrack) {
|
||||
msg = '做空 触发价: ' + Bar.Close + ' 下轨:' + DownTrack;
|
||||
Log(msg);
|
||||
sellInfo = $.Sell(AmountOP); //Trade(State, STATE_SHORT);
|
||||
//chart.add(1, {x:Bar.Time, color: 'green', shape: 'circlepin', title: '空', text: msg});
|
||||
Log("sellInfo:",sellInfo);
|
||||
if(sellInfo === null){
|
||||
return;
|
||||
}
|
||||
State = STATE_SHORT;
|
||||
if(NowPositionInfo.direction === NONE){
|
||||
NowPositionInfo.direction = SHORT;
|
||||
fcolor = 'green';
|
||||
ftitle = '空';
|
||||
}else if(NowPositionInfo.direction === LONG){
|
||||
State = STATE_IDLE;
|
||||
NowPositionInfo.direction = NONE;
|
||||
Calculate();
|
||||
//Profit = (nowAccount.Stocks - beginAccount.Stocks) * (NowPositionInfo.direction === SHORT?nowDepth.Bids[0].Price : nowDepth.Asks[0].Price) + (beginAccount.Balance - nowAccount.Balance); //总盈亏
|
||||
InitAccount = _C(exchange.GetAccount);
|
||||
LogProfit(Profit,InitAccount);
|
||||
fcolor = 'blue';
|
||||
ftitle = '平';
|
||||
isTrade_OC = true;//当前bar 已经交易
|
||||
}
|
||||
chart.add(1, {x:Bar.Time, color: fcolor, shape: 'circlepin', title: ftitle, text: msg});
|
||||
}
|
||||
}
|
||||
|
||||
if( (State === STATE_SHORT && NowPositionInfo.direction === SHORT ) || ( NowPositionInfo.direction === LONG && State === STATE_LONG) ){
|
||||
if(NowPositionInfo.floatProfit >= maxProfit ){
|
||||
//cover
|
||||
if(NowPositionInfo.direction === SHORT){
|
||||
buyInfo = $.Buy(NowPositionInfo.amount);
|
||||
if(buyInfo === null){
|
||||
return;
|
||||
}
|
||||
State = STATE_IDLE;
|
||||
NowPositionInfo.direction = NONE;
|
||||
Calculate();
|
||||
InitAccount = _C(exchange.GetAccount);
|
||||
LogProfit(Profit,InitAccount);
|
||||
fcolor = 'blue';
|
||||
ftitle = '止盈 平仓';
|
||||
isTrade_OC = true;//当前bar 已经交易
|
||||
}
|
||||
if(NowPositionInfo.direction === LONG){
|
||||
sellInfo = $.Sell(NowPositionInfo.amount);
|
||||
if(sellInfo === null){
|
||||
return;
|
||||
}
|
||||
State = STATE_IDLE;
|
||||
NowPositionInfo.direction = NONE;
|
||||
Calculate();
|
||||
InitAccount = _C(exchange.GetAccount);
|
||||
LogProfit(Profit,InitAccount);
|
||||
fcolor = 'blue';
|
||||
ftitle = '止盈 平仓';
|
||||
isTrade_OC = true;//当前bar 已经交易
|
||||
}
|
||||
chart.add(1, {x:Bar.Time, color: fcolor, shape: 'circlepin', title: ftitle, text: msg});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//var OpAmount = 1;//ceshi
|
||||
//var maxProfit = 0.2;
|
||||
var buyInfo = null;
|
||||
var sellInfo = null;
|
||||
var SHORT = 2;
|
||||
var LONG = 1;
|
||||
var NONE = 0;
|
||||
var NowPositionInfo = { //
|
||||
avgPrice : 0 ,
|
||||
amount : 0,
|
||||
floatProfit : 0,
|
||||
direction : 0 // 0 未持仓 , 1多仓 , 2空仓
|
||||
};
|
||||
|
||||
|
||||
function onexit() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
var Profit = 0;
|
||||
function Calculate(nowAccount,nowDepth){//计算并更新收益 、 浮动收益 、计算 持仓均价 、持仓量
|
||||
if(typeof(nowAccount) === 'undefined' ){
|
||||
nowAccount = _C(exchange.GetAccount);
|
||||
nowDepth = _C(exchange.GetDepth);
|
||||
}
|
||||
var diff_stocks = nowAccount.Stocks - InitAccount.Stocks;//币之差
|
||||
var diff_balance = nowAccount.Balance - InitAccount.Balance;//钱之差
|
||||
NowPositionInfo.avgPrice = Math.abs(diff_balance) / Math.abs(diff_stocks);
|
||||
//throw nowAccount.Stocks + "----" + nowAccount.Balance;//ceshi
|
||||
NowPositionInfo.amount = Math.abs(diff_stocks);
|
||||
NowPositionInfo.floatProfit = diff_balance + diff_stocks * (NowPositionInfo.direction === SHORT?nowDepth.Bids[0].Price : nowDepth.Asks[0].Price); //此次交易的浮动盈亏
|
||||
Profit = (nowAccount.Stocks - beginAccount.Stocks) * (NowPositionInfo.direction === SHORT?nowDepth.Bids[0].Price : nowDepth.Asks[0].Price) + (nowAccount.Balance - beginAccount.Balance); //总盈亏
|
||||
|
||||
//更新入界面
|
||||
}
|
||||
|
||||
function main() {
|
||||
CancelPendingOrders();
|
||||
InitAccount = exchange.GetAccount();//上次平仓后账户信息
|
||||
beginAccount = InitAccount; //启动时账户信息
|
||||
LoopInterval = Math.min(1, LoopInterval);
|
||||
//清空
|
||||
LogReset();
|
||||
LogProfitReset();
|
||||
chart = Chart(ChartCfg);
|
||||
chart.reset();
|
||||
|
||||
Log('交易平台:', exchange.GetName(), InitAccount);
|
||||
LogStatus("Ready...");
|
||||
Log(InitAccount);
|
||||
|
||||
LoopInterval = Math.max(LoopInterval, 1);
|
||||
while (true) {
|
||||
onTick(exchange);
|
||||
Calculate();
|
||||
Sleep(LoopInterval * 1000);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/36875
|
||||
策略名称: Jason
|
||||
策略作者: jason123456
|
||||
策略描述:
|
||||
|
||||
求梦神指点
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
------- ----- ----
|
||||
symbolA MA705 合约1
|
||||
symbolB MA709 合约2
|
||||
|
||||
按钮 默认值 描述
|
||||
-------- ---------- ----
|
||||
CoverAll __button__ 全部平仓
|
||||
*/
|
||||
|
||||
var preRecordsTime=0;
|
||||
var symbolA=symbolA
|
||||
var symbolB=symbolB
|
||||
function main() {
|
||||
var isFirst = true // 设置一个变量 表示第一次循环
|
||||
var cfg = $.GetCfg();
|
||||
cfg.yAxis = [{
|
||||
title: {text: 'K线'},//标题
|
||||
style: {color: '#4572A7'},//样式
|
||||
opposite: false //生成右边Y轴
|
||||
},
|
||||
{
|
||||
title:{text: "A"},
|
||||
opposite: true //生成右边Y轴 ceshi
|
||||
}
|
||||
];
|
||||
|
||||
while (true) {
|
||||
exchange.SetContractType(symbolA);
|
||||
Log('hello')//这里可以打印出来,说明错误在这前面还是后面?
|
||||
var recordsA = exchange.GetRecords(); // 获取K线数据
|
||||
if (recordsA && recordsA.length > 0) { // records 不为 null 并且 不是 空数组
|
||||
$.PlotRecords(recordsA, symbolA) // 调用 模板导出函数 $.PlotRecords 传入 K线数据 和 标题 BTC
|
||||
if (isFirst) { // 如果是第一次循环 执行以下
|
||||
$.PlotFlag(recordsA[recordsA.length - 1].Time, 'Start', 'S') // 添加一个 旗帜标记
|
||||
isFirst = false // 更新isFirst 下次不会在执行符合当前 if 条件的代码
|
||||
//$.PlotHLine(records[records.length - 1].Close, 'Close') // 画一条水平线
|
||||
}
|
||||
}
|
||||
var recordsB = exchange.GetRecords(symbolB); // 获取K线数据
|
||||
if (recordsB && recordsB.length > 0) { // records 不为 null 并且 不是 空数组
|
||||
$.PlotRecords(recordsB, symbolB) // 调用 模板导出函数 $.PlotRecords 传入 K线数据 和 标题 BTC
|
||||
if (isFirst) { // 如果是第一次循环 执行以下
|
||||
$.PlotFlag(recordsB[recordsB.length - 1].Time, 'Start', 'S') // 添加一个 旗帜标记
|
||||
isFirst = false // 更新isFirst 下次不会在执行符合当前 if 条件的代码
|
||||
//$.PlotHLine(records[records.length - 1].Close, 'Close') // 画一条水平线
|
||||
}
|
||||
}
|
||||
|
||||
// LINEARREG_SLOPE
|
||||
var slopeA = talib.LINEARREG_SLOPE(recordsA,10);
|
||||
if(preRecordsTime !== recordsA[recordsA.length - 1].Time){
|
||||
$.PlotLine('slopeA', slopeA[slopeA.length - 1]);
|
||||
for(var j = 0;j < cfg.series.length; j++){
|
||||
if(cfg.series[j].name == "slopeA"){
|
||||
cfg.series[j].yAxis = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
preRecordsTime = recordsA[recordsA.length - 1].Time;
|
||||
var slopeB = talib.LINEARREG_SLOPE(recordsB,10);
|
||||
if(preRecordsTime !== recordsB[recordsB.length - 1].Time){
|
||||
$.PlotLine('slopeB', slopeB[slopeB.length - 1]);
|
||||
for(var k = 0;k < cfg.series.length; k++){
|
||||
if(cfg.series[k].name == "slopeB"){
|
||||
cfg.series[k].yAxis = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
preRecordsTime = recordsB[recordsB.length - 1].Time;
|
||||
|
||||
Sleep(1000)
|
||||
}
|
||||
}
|
||||
+37
-3
@@ -372,6 +372,36 @@ function DealActionLimit(task, AorB, Piece, isAgain){
|
||||
return tradeInfo;
|
||||
}
|
||||
|
||||
function CalcActualPrice(task){
|
||||
if(task.action[0] == 0){
|
||||
var A_Pv = task.APositions.Price;
|
||||
var B_Pv = task.BPositions.Price;
|
||||
task.dic[task.action[0]].ActualPrice = A_Pv - B_Pv;
|
||||
Log(task.symbolA, A_Pv, task.symbolB, B_Pv, "#FF0000");
|
||||
}else if(task.APositions.Amount == 1 && task.BPositions.Amount == 1){
|
||||
var A_Pv = task.APositions.Price;
|
||||
var B_Pv = task.BPositions.Price;
|
||||
task.dic[task.action[0]].ActualPrice = A_Pv - B_Pv;
|
||||
Log(task.symbolA, A_Pv, task.symbolB, B_Pv, "#FF0000");
|
||||
}else{
|
||||
var A_Pv = task.APositions.Price;
|
||||
var A_P1 = task.Pre_APositions.Price;
|
||||
var A_m = task.APositions.Amount - task.Pre_APositions.Amount;
|
||||
var A_n = task.Pre_APositions.Amount;
|
||||
|
||||
var B_Pv = task.BPositions.Price;
|
||||
var B_P1 = task.Pre_BPositions.Price;
|
||||
var B_m = task.BPositions.Amount - task.Pre_BPositions.Amount;
|
||||
var B_n = task.Pre_BPositions.Amount;
|
||||
|
||||
var A_P2 = A_Pv * A_P1 * A_m / ((A_m + A_n) * A_P1 - A_n * A_Pv);
|
||||
var B_P2 = B_Pv * B_P1 * B_m / ((B_m + B_n) * B_P1 - B_n * B_Pv);
|
||||
|
||||
task.dic[task.action[0]].ActualPrice = A_P2 - B_P2;
|
||||
Log(task.symbolA, A_P2, task.symbolB, B_P2, "#FF0000");
|
||||
}
|
||||
}
|
||||
|
||||
function Hedge_Open_Cover(task){
|
||||
if(task.isUseMarketOrder === false){ // 限价单
|
||||
if((task.action[1] === "buy" && task.action[2] === "sell") || (task.action[1] === "sell" && task.action[2] === "buy")){ // open
|
||||
@@ -510,6 +540,8 @@ function TasksController(){ // 任务控制器 构造函数
|
||||
FrozenStartTime : 0,
|
||||
APositions : null,
|
||||
BPositions : null,
|
||||
Pre_APositions : null,
|
||||
Pre_BPositions : null,
|
||||
PositionsLastUpdateTime : 0,
|
||||
isLogProfit : false,
|
||||
taskProfit : 0,
|
||||
@@ -620,8 +652,9 @@ function TasksController(){ // 任务控制器 构造函数
|
||||
task.isLogProfit = false;
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
UpdatePosition(task, Positions, PRE);
|
||||
Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
CalcActualPrice(task);
|
||||
task.State = PLUS;
|
||||
}else if(task.dic[index].open <= -task.Bdiff && task.State !== PLUS){ // 反对冲 多A 空B
|
||||
task.action = [index, "buy", "sell", -task.dic[index].amount];
|
||||
@@ -632,8 +665,9 @@ function TasksController(){ // 任务控制器 构造函数
|
||||
task.isLogProfit = false;
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
UpdatePosition(task, Positions, PRE);
|
||||
Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
CalcActualPrice(task);
|
||||
task.State = MINUS;
|
||||
}else{
|
||||
SumHold--;
|
||||
@@ -691,7 +725,7 @@ function TasksController(){ // 任务控制器 构造函数
|
||||
for(var key in task){
|
||||
value = task[key];
|
||||
if(key === "dic" || key === "Adepth" || key === "Bdepth" || key === "initAccount" || key === "nowAccount" || key === "isFrozen" ||
|
||||
key === "FrozenStartTime" || key === "P"){ // 过滤显示
|
||||
key === "FrozenStartTime" || key === "P" || key === "Pre_APositions" || key === "Pre_BPositions"){ // 过滤显示
|
||||
continue;
|
||||
}
|
||||
if(key === "e"){
|
||||
|
||||
@@ -4,12 +4,21 @@
|
||||
> 开源策略列表
|
||||
|
||||
|
||||
- [Jason](https://www.botvs.com/strategy/36875)
|
||||
- [测试多图表展示](https://www.botvs.com/strategy/38203)
|
||||
- [商品期货结算单平仓盈亏历史查询](https://www.botvs.com/strategy/38083)
|
||||
- [Convert_Record_Cycle](https://www.botvs.com/strategy/37678)
|
||||
- [商品期货查看账户详细信息](https://www.botvs.com/strategy/37793)
|
||||
- [商品期货交易类库](https://www.botvs.com/strategy/12961)
|
||||
- [均线-趋势_数字货币策略V0.2 (Copy)](https://www.botvs.com/strategy/37664)
|
||||
- [数字货币交易类库 (期货支持OKCoin期货/BitVC)](https://www.botvs.com/strategy/30199)
|
||||
- [转换任意K线周期](https://www.botvs.com/strategy/35986)
|
||||
- [OKCoin期货跨期对冲策略](https://www.botvs.com/strategy/34878)
|
||||
- [API 测试新手入门](https://www.botvs.com/strategy/4)
|
||||
- [实盘账户模拟器](https://www.botvs.com/strategy/35977)
|
||||
- [js R-Breaker](https://www.botvs.com/strategy/36195)
|
||||
- [图表界面信息展示实例1](https://www.botvs.com/strategy/36026)
|
||||
- [移植 OKCoin 韭菜收割机](https://www.botvs.com/strategy/34388)
|
||||
- [R-Breaker11 交易策略](https://www.botvs.com/strategy/23874)
|
||||
- [商品期货交易类库](https://www.botvs.com/strategy/12961)
|
||||
- [商品期货套利 - 多品种网格对冲模型](https://www.botvs.com/strategy/27799)
|
||||
- [比特币现货阶梯差价对冲](https://www.botvs.com/strategy/30573)
|
||||
- [策略框架模板](https://www.botvs.com/strategy/30861)
|
||||
@@ -17,7 +26,6 @@
|
||||
- [python版 Dual Thrust OKCoin 期货](https://www.botvs.com/strategy/21856)
|
||||
- [测试-布林带策略(基于策略框架) (复制)](https://www.botvs.com/strategy/31456)
|
||||
- [国外知名策略R-Breaker (复制)](https://www.botvs.com/strategy/30512)
|
||||
- [数字货币交易类库 (期货支持OKCoin期货/BitVC)](https://www.botvs.com/strategy/30199)
|
||||
- [范例-定时测试微信消息推送](https://www.botvs.com/strategy/15098)
|
||||
- [测试-布林带策略(基于策略框架)](https://www.botvs.com/strategy/28128)
|
||||
- [CTP商品期货多品种海龟交易策略](https://www.botvs.com/strategy/17289)
|
||||
@@ -31,6 +39,7 @@
|
||||
- [全球10大交易系统之 Aberration 多品种商品期货交易系统](https://www.botvs.com/strategy/25943)
|
||||
- [获取和讯期货数据(Python版本)](https://www.botvs.com/strategy/26017)
|
||||
- [高频收割机一号](https://www.botvs.com/strategy/6237)
|
||||
- [Dual Thrust (现货版)](https://www.botvs.com/strategy/21583)
|
||||
- [R-Breaker 交易策略](https://www.botvs.com/strategy/23531)
|
||||
- [多平台对冲稳定套利 V2.1 (复制)](https://www.botvs.com/strategy/23718)
|
||||
- [(13)策略框架](https://www.botvs.com/strategy/20663)
|
||||
@@ -47,6 +56,7 @@
|
||||
- [均线-趋势_数字货币策略V0.2](https://www.botvs.com/strategy/21369)
|
||||
- [Python简单测试策略](https://www.botvs.com/strategy/20761)
|
||||
- [数字货币现货交易类库](https://www.botvs.com/strategy/10989)
|
||||
- [图表模板(增加状态栏表格)](https://www.botvs.com/strategy/20967)
|
||||
- [高频交易策略之 - Penny Jump](https://www.botvs.com/strategy/358)
|
||||
- [MACD低买高卖自动跟单滑动止损 (复制)](https://www.botvs.com/strategy/20266)
|
||||
- [获取周K线](https://www.botvs.com/strategy/20226)
|
||||
@@ -100,7 +110,6 @@
|
||||
- [OKCoin期货条件触发委托带止损](https://www.botvs.com/strategy/2169)
|
||||
- [监视并显示多个平台的全部资产总和的变化](https://www.botvs.com/strategy/443)
|
||||
- [多平台对冲稳定套利 V2.1](https://www.botvs.com/strategy/57)
|
||||
- [API 测试新手入门](https://www.botvs.com/strategy/4)
|
||||
- [抢盘口做市策略 - 对敲](https://www.botvs.com/strategy/304)
|
||||
- [Dual Thrust (可做多做空,震荡型)](https://www.botvs.com/strategy/351)
|
||||
- [统计BitVC动态权益/OKCoin已经实现盈亏/796账户余额](https://www.botvs.com/strategy/1483)
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/36195
|
||||
策略名称: js R-Breaker
|
||||
策略作者: 太极
|
||||
策略描述:
|
||||
|
||||
R-Breaker
|
||||
|
||||
*/
|
||||
|
||||
NPeriod=2 //周期
|
||||
f1=0.47 //中轨上下顶部区间系数
|
||||
f2=0.07 //中轨上下区间系数
|
||||
f3=0.25 //上下轨系数
|
||||
|
||||
//==========================================
|
||||
//API: Chart 函数使用的简单例子(画图功能)
|
||||
var chart = { // 这个 chart 在JS 语言中 是对象, 在使用Chart 函数之前我们需要声明一个配置图表的对象变量chart。
|
||||
__isStock: true, // 标记是否为一般图表,有兴趣的可以改成 false 运行看看。
|
||||
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // 缩放工具
|
||||
title : { text : '行情分析图'}, // 标题
|
||||
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
|
||||
},
|
||||
xAxis: { type: 'datetime'}, // 坐标轴横轴 即:x轴, 当前设置的类型是 :时间
|
||||
yAxis : { // 坐标轴纵轴 即:y轴, 默认数值随数据大小调整。
|
||||
title:{text: '行情演算'}, // 标题
|
||||
opposite:false, // 是否启用右边纵轴
|
||||
},
|
||||
series : [ // 数据系列,该属性保存的是 各个 数据系列(线, K线图, 标签等..)
|
||||
{name:"0X",id:"0",color:'#FF83FA',data:[]},
|
||||
{name:"1X",id:"1",color:'#FF3E96',dashStyle:'shortdash',data:[]},
|
||||
{name:"2X",id:"2",color:'#FF0000',data:[]},
|
||||
|
||||
{name:"3X",id:"3",color:'#7D26CD',dashStyle:'shortdash',data:[]}, //
|
||||
|
||||
{name:"4X",id:"4",color:'#2B2B2B',data:[]},
|
||||
{name:"5X",id:"5",color:'#707070',dashStyle:'shortdash',data:[]},
|
||||
{name:"6X",id:"6",color:'#778899',data:[]},
|
||||
|
||||
{name:"7X",id:"7",color:'#0000CD',data:[]},
|
||||
|
||||
//RGB颜色对照表 http://www.114la.com/other/rgb.htm
|
||||
]
|
||||
};
|
||||
|
||||
/*
|
||||
//Pivot Points策略
|
||||
chart["series"][0]["name"]="阻力3:";
|
||||
chart["series"][1]["name"]="阻力2:";
|
||||
chart["series"][2]["name"]="阻力1:";
|
||||
|
||||
chart["series"][3]["name"]="枢轴点:";
|
||||
|
||||
chart["series"][4]["name"]="支撑位1:";
|
||||
chart["series"][5]["name"]="支撑位2:";
|
||||
chart["series"][6]["name"]="支撑位3:";
|
||||
chart["series"][6]["name"]="当前价格:";
|
||||
*/
|
||||
///*
|
||||
//R-Breaker策略
|
||||
chart["series"][0]["name"]="Bbreak_A1:";
|
||||
chart["series"][1]["name"]="Ssetup_A2:";
|
||||
chart["series"][2]["name"]="Senter_A3:";
|
||||
|
||||
chart["series"][4]["name"]="Benter_B1:";
|
||||
chart["series"][5]["name"]="Sbreak_B2:";
|
||||
chart["series"][6]["name"]="Bsetup_B3:";
|
||||
chart["series"][7]["name"]="当前价格:";
|
||||
//*/
|
||||
|
||||
|
||||
var ObjChart = Chart(chart); // 调用 Chart 函数,初始化 图表。
|
||||
ObjChart.reset(); // 清空
|
||||
function onTick(e){
|
||||
var records = _C(e.GetRecords); //返回一个K线历史
|
||||
var ticker = _C(e.GetTicker); //返回一个Ticker结构
|
||||
var account = _C(e.GetAccount); //返回主交易所账户信息
|
||||
|
||||
var High = TA.Highest(records, NPeriod, 'High'); //最高价
|
||||
var Close = TA.Lowest(records, NPeriod, 'Close'); //收盘价
|
||||
var Low = TA.Lowest(records, NPeriod, 'Low'); //最低价
|
||||
|
||||
/*
|
||||
//Pivot Points策略
|
||||
//A上 7235 A中 7259 A下 7275 B上 7195 B中 7155 B下 7179
|
||||
Pivot = (High+Close+Low)/3 //枢轴点
|
||||
|
||||
var Senter=High+2*(Pivot-Low) //阻力3
|
||||
var Ssetup=Pivot+(High-Low) //阻力2
|
||||
var Bbreak=2*Pivot-Low //阻力1
|
||||
|
||||
var Benter=2*Pivot-High //支撑位1
|
||||
var Sbreak=Pivot-(High-Low) //支撑位2
|
||||
var Bsetup=Low-2*(High-Pivot) //支撑位3
|
||||
//画线
|
||||
var nowTime = new Date().getTime(); //获取时间戳,
|
||||
ObjChart.add([0, [nowTime,_N(Senter,3)]]); //阻力3
|
||||
ObjChart.add([1, [nowTime,_N(Ssetup,3)]]); //阻力2
|
||||
ObjChart.add([2, [nowTime,_N(Bbreak,3)]]); //阻力1
|
||||
|
||||
ObjChart.add([3, [nowTime,_N(Pivot,3)]]); //枢轴点
|
||||
|
||||
ObjChart.add([4, [nowTime,_N(Benter,3)]]); //支撑位1
|
||||
ObjChart.add([5, [nowTime,_N(Sbreak,3)]]); //支撑位2
|
||||
ObjChart.add([6, [nowTime,_N(Bsetup,3)]]); //支撑位3
|
||||
|
||||
ObjChart.add([7, [nowTime,_N(ticker.Last,3)]]); //最后成交价
|
||||
|
||||
ObjChart.update(chart); // 更新图表以显示出来。
|
||||
*/
|
||||
|
||||
|
||||
///*
|
||||
//R-Breaker策略
|
||||
//A上 7261.46 A中 7246.76 A下 7228.68 B上 7204.48 B中 7187.96 B下 7173.26
|
||||
var Ssetup = High + f1 * (Close - Low); //A中
|
||||
var Bsetup = Low - f1 * (High - Close); //B下
|
||||
|
||||
var Bbreak = Ssetup + f3 * (Ssetup - Bsetup); //A上
|
||||
var Senter = ((1 + f2) / 2) * (High + Close) - f2 * Low; //A下
|
||||
|
||||
var Benter = ((1 + f2) / 2) * (Low + Close) - f2 * High; //B上
|
||||
var Sbreak = Bsetup - f3 * (Ssetup - Bsetup); //B中
|
||||
//画线
|
||||
var nowTime = new Date().getTime(); //获取时间戳,
|
||||
ObjChart.add([0, [nowTime,_N(Bbreak,3)]]); //A上
|
||||
ObjChart.add([1, [nowTime,_N(Ssetup,3)]]); //A中
|
||||
ObjChart.add([2, [nowTime,_N(Senter,3)]]); //A下
|
||||
|
||||
//ObjChart.add([3, [nowTime,_N(Pivot,3)]]); //枢轴点
|
||||
|
||||
ObjChart.add([4, [nowTime,_N(Benter,3)]]); //B上
|
||||
ObjChart.add([5, [nowTime,_N(Sbreak,3)]]); //B中
|
||||
ObjChart.add([6, [nowTime,_N(Bsetup,3)]]); //B下
|
||||
|
||||
ObjChart.add([7, [nowTime,_N(ticker.Last,3)]]); //最后成交价
|
||||
|
||||
ObjChart.update(chart); // 更新图表以显示出来。
|
||||
//*/
|
||||
|
||||
Log('A上',_N(Bbreak,3),'A中',_N(Ssetup,3),'A下',_N(Senter,3),'B上',_N(Benter,3),'B中',_N(Bsetup,3),'B下',_N(Sbreak,3));
|
||||
}
|
||||
|
||||
|
||||
|
||||
function main() {
|
||||
Log("策略启动");
|
||||
while(true){
|
||||
onTick(exchanges[0]);
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-1
@@ -38,7 +38,7 @@ function main() {
|
||||
Interval 500 失败重试间隔(毫秒)
|
||||
SlideTick true 滑价点数(整数)
|
||||
RiskControl false 开启风控
|
||||
MaxTrade 50 工作日最多交易交易次数
|
||||
MaxTrade 100 工作日最多交易交易次数
|
||||
MaxTradeAmount 1000 单笔最多下单量
|
||||
*/
|
||||
|
||||
@@ -700,6 +700,7 @@ $.NewTaskQueue = function(onTaskFinish) {
|
||||
if (processed == 0) {
|
||||
self.tasks = []
|
||||
}
|
||||
return processed
|
||||
}
|
||||
|
||||
self.size = function() {
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/37793
|
||||
策略名称: 商品期货查看账户详细信息
|
||||
策略作者: Zero
|
||||
策略描述:
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
var trans = {
|
||||
"AccountID": "投资者帐号",
|
||||
"Available": "可用资金",
|
||||
"Balance": "期货结算准备金",
|
||||
"BrokerID": "经纪公司代码",
|
||||
"CashIn": "资金差额",
|
||||
"CloseProfit": "平仓盈亏",
|
||||
"Commission": "手续费",
|
||||
"Credit": "信用额度",
|
||||
"CurrMargin": "当前保证金总额",
|
||||
"CurrencyID": "币种代码",
|
||||
"DeliveryMargin": "投资者交割保证金",
|
||||
"Deposit": "入金金额",
|
||||
"ExchangeDeliveryMargin": "交易所交割保证金",
|
||||
"ExchangeMargin": "交易所保证金",
|
||||
"FrozenCash": "冻结的资金",
|
||||
"FrozenCommission": "冻结的手续费",
|
||||
"FrozenMargin": "冻结的保证金",
|
||||
"FundMortgageAvailable": "货币质押余额",
|
||||
"FundMortgageIn": "货币质入金额",
|
||||
"FundMortgageOut": "货币质出金额",
|
||||
"Interest": "利息收入",
|
||||
"InterestBase": "利息基数",
|
||||
"Mortgage": "质押金额",
|
||||
"MortgageableFund": "可质押货币金额",
|
||||
"PositionProfit": "持仓盈亏",
|
||||
"PreBalance": "上次结算准备金",
|
||||
"PreCredit": "上次信用额度",
|
||||
"PreDeposit": "上次存款额",
|
||||
"PreFundMortgageIn": "上次货币质入金额",
|
||||
"PreFundMortgageOut": "上次货币质出金额",
|
||||
"PreMargin": "上次占用的保证金",
|
||||
"PreMortgage": "上次质押金额",
|
||||
"Reserve": "基本准备金",
|
||||
"ReserveBalance": "保底期货结算准备金",
|
||||
"SettlementID": "结算编号",
|
||||
"SpecProductCloseProfit": "特殊产品持仓盈亏",
|
||||
"SpecProductCommission": "特殊产品手续费",
|
||||
"SpecProductExchangeMargin": "特殊产品交易所保证金",
|
||||
"SpecProductFrozenCommission": "特殊产品冻结手续费",
|
||||
"SpecProductFrozenMargin": "特殊产品冻结保证金",
|
||||
"SpecProductMargin": "特殊产品占用保证金",
|
||||
"SpecProductPositionProfit": "特殊产品持仓盈亏",
|
||||
"SpecProductPositionProfitByAlg": "根据持仓盈亏算法计算的特殊产品持仓盈亏",
|
||||
"TradingDay": "交易日",
|
||||
"Withdraw": "出金金额",
|
||||
"WithdrawQuota": "可取资金",
|
||||
};
|
||||
|
||||
function AccountToTable(jsStr, title) {
|
||||
if (typeof(title) === 'undefined') {
|
||||
title = '账户信息';
|
||||
}
|
||||
var tbl = {
|
||||
type: "table",
|
||||
title: title,
|
||||
cols: ["字段", "描述", "值"],
|
||||
rows: []
|
||||
};
|
||||
try {
|
||||
var fields = JSON.parse(jsStr);
|
||||
for (var k in fields) {
|
||||
if (k == 'AccountID' || k == 'BrokerID') {
|
||||
continue
|
||||
}
|
||||
var desc = trans[k];
|
||||
var v = fields[k];
|
||||
if (typeof(v) === 'number') {
|
||||
v = _N(v, 5);
|
||||
}
|
||||
tbl.rows.push([k, typeof(desc) === 'undefined' ? '--' : desc, v]);
|
||||
}
|
||||
} catch (e) {}
|
||||
return tbl;
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
var account = _C(exchange.GetAccount);
|
||||
var raw = exchange.GetRawJSON()
|
||||
LogStatus('`' + JSON.stringify(AccountToTable(raw))+'`')
|
||||
Log(raw)
|
||||
Log("已经在状态栏以表格形式显示")
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/38083
|
||||
策略名称: 商品期货结算单平仓盈亏历史查询
|
||||
策略作者: Zero
|
||||
策略描述:
|
||||
|
||||
需要更新最新的托管者, 不支持回测, 只支持实盘
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
--------- ---------- ----
|
||||
StartDate 2017-03-15 开始日期
|
||||
EndDate 2017-03-17 结束日期
|
||||
*/
|
||||
|
||||
function main() {
|
||||
var cfg = {
|
||||
tooltip: {
|
||||
xDateFormat: '%Y-%m-%d %H:%M:%S, %A'
|
||||
},
|
||||
title: {
|
||||
text: '平仓盈亏分析图'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime'
|
||||
},
|
||||
series: [{
|
||||
name: '平仓盈亏',
|
||||
data: [],
|
||||
tooltip: {
|
||||
valueDecimals: 2
|
||||
}
|
||||
}]
|
||||
}
|
||||
var chart = Chart(cfg);
|
||||
|
||||
chart.reset();
|
||||
Log("开始查询结算单...")
|
||||
var ts = new Date(StartDate + " 00:00:00")
|
||||
var te = new Date(EndDate + " 00:00:00");
|
||||
var now = new Date();
|
||||
if (te.getTime() > now.getTime()) {
|
||||
te = now;
|
||||
}
|
||||
var preDate = ""
|
||||
var AllProfit = 0
|
||||
var AllCommission = 0;
|
||||
while (ts.getTime() < te.getTime()) {
|
||||
var day = _D(ts, "yyyyMMdd");
|
||||
LogStatus("正在查询 " + day);
|
||||
r = _C(exchange.IO, "settlement", day)
|
||||
var m = r.Content.match(/Creation Date.\s*(\d+)/)
|
||||
if (m) {
|
||||
var date = m[1]
|
||||
m = r.Content.match(/Realized P\/L.\s*([\-\.\d]+)/)
|
||||
m2 = r.Content.match(/Commission.\s*([\-\.\d]+)/)
|
||||
if (m && m2 && preDate != date) {
|
||||
preDate = date
|
||||
var profit = parseFloat(m[1])
|
||||
var commission = parseFloat(m2[1])
|
||||
AllProfit += profit;
|
||||
AllCommission += commission
|
||||
cfg.subtitle = {
|
||||
text: '总平仓盈亏:' + _N(AllProfit) + ', 总手续费:' + _N(AllCommission)
|
||||
};
|
||||
chart.update(cfg);
|
||||
chart.add([0, [ts.getTime(), profit]]);
|
||||
LogStatus("All Profit:", AllProfit);
|
||||
Log(date, "平仓盈亏", profit, "手续费", commission);
|
||||
}
|
||||
}
|
||||
Sleep(1000)
|
||||
ts = new Date(ts.getTime() + (24 * 60 * 60000))
|
||||
}
|
||||
Log("查询完成, 总平仓盈亏:", _N(AllProfit), "总手续费:", _N(AllCommission));
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/20967
|
||||
策略名称: 图表模板(增加状态栏表格)
|
||||
策略作者: 小小梦
|
||||
策略描述:
|
||||
|
||||
图表模板
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
-------------- ----- --------
|
||||
indicatorsName 指标轴1 指标轴
|
||||
indicators_1 指标1 指标1
|
||||
indicators_2 指标2 指标2
|
||||
Interval 500 间隔(毫秒)
|
||||
isOpenRightY true 是否开启右边Y轴
|
||||
lineType line 指标线类型
|
||||
*/
|
||||
|
||||
/*
|
||||
这个是一个图表模板,详细用法见广场帖子。
|
||||
*/
|
||||
//----------------------------------图表模块----------------------------------------------------------------
|
||||
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: isOpenRightY //生成右边Y轴 ceshi
|
||||
}
|
||||
],
|
||||
series: [//系列
|
||||
{type:'candlestick',yAxis:0,name:'K',id:'KLine',data:[]},
|
||||
{type:'flags',onSeries:'KLine',data:[]},
|
||||
{name:indicators_1,type:lineType,yAxis:isOpenRightY?1:0,data:[]},
|
||||
{name:indicators_2,type:lineType,yAxis:isOpenRightY?1:0,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 lastRecordsTime = 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,message){
|
||||
var msg = "";
|
||||
var fcolor = ""; // ceshi
|
||||
var strState = "";//ceshi
|
||||
msg = "均价:"+price+"币数:"+amount;
|
||||
switch(state){
|
||||
case 3:strState = "自定义信息";fcolor = "black";msg = message;break;
|
||||
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});
|
||||
}
|
||||
//----------------------------------图表模块over------------------------------------------------------------
|
||||
//----------------------------------状态栏表格模块-----------------------------------------------------------
|
||||
var TV = null; //表格对象,控制表格内容。
|
||||
var objTable = null;//用于显示表格的对象。
|
||||
function CreateObjectString(cols,rows){
|
||||
var i = cols;// column 列
|
||||
var j = rows;// row 行
|
||||
var firstCols = 'a';
|
||||
var charValue = 0;
|
||||
var firstName = ""; //对象字符串成员的字母部分
|
||||
var lastName = ""; //对象字符串成员的数字部分
|
||||
var strMember = ""; //对象字符串成员
|
||||
var objStr = "";//返回的字符串
|
||||
if(i > 26){
|
||||
throw "ERROR column must less 26";
|
||||
}
|
||||
var strHead = '{';
|
||||
var strEnd = '}';
|
||||
for(var n = 0 ; n < j; n++){
|
||||
//处理行
|
||||
for(var m = 0 ; m < i; m++){
|
||||
//处理列 处理 abc , 数字=n
|
||||
charValue = firstCols.charCodeAt();//取字符的编码
|
||||
firstName = String.fromCharCode(charValue + m);
|
||||
lastName = n;
|
||||
if(n === j - 1 && m === i - 1 ){
|
||||
strMember = '"' + firstName + lastName + '"' + ':' + '""';
|
||||
}else{
|
||||
strMember = '"' + firstName + lastName + '"' + ':' + '""' + ',';
|
||||
}
|
||||
objStr += strMember;
|
||||
}
|
||||
}
|
||||
objStr = strHead + objStr + strEnd;
|
||||
return objStr;
|
||||
}
|
||||
|
||||
var g_cols = 0;
|
||||
var g_rows = 0;
|
||||
$.TableInit = function(cols,rows){
|
||||
g_cols = cols;
|
||||
g_rows = rows;
|
||||
var str = CreateObjectString(cols,rows);//生成 TV对象 字符串
|
||||
TV = JSON.parse(str); // 解析字符串生成 TV对象
|
||||
var tableString = CreateTableString(cols,rows);//生成表格对象字符串
|
||||
objTable = JSON.parse(tableString);//解析表格对象字符串
|
||||
LogStatus("当前时间:" + (new Date()) + "\n" + "`" + JSON.stringify(objTable) + "`");//初次显示 表格对象到 状态栏
|
||||
//ConnectDate(cols,rows);//初次链接数据
|
||||
return TV;//返回 TV对象
|
||||
};
|
||||
function ConnectDate(cols,rows){//关联函数
|
||||
//处理cols
|
||||
var i = 0;//控制 objTable.cols
|
||||
for(var unit1 in TV){
|
||||
if(i < cols){
|
||||
objTable.cols[i] = TV[unit1];
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//处理rows
|
||||
var m = 0;//m控制 第几行
|
||||
var n = 0;//n控制 第几个
|
||||
var o = 1;//跳过cols 部分的计数
|
||||
for(var unit2 in TV){
|
||||
if( o <= cols){
|
||||
o++;
|
||||
continue;
|
||||
}
|
||||
if(n >= cols){
|
||||
n = 0;
|
||||
m++;
|
||||
}
|
||||
objTable.rows[m][n] = TV[unit2];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
function CreateTableString(cols,rows){
|
||||
var strHead = '{';
|
||||
var strEnd = '}';
|
||||
var srtTable_type = ' "type": "table",';
|
||||
var strTable_title = ' "title": "运行信息",';
|
||||
var strTable_cols_begin = ' "cols" : [';
|
||||
var strTable_cols_end = '],';
|
||||
var strTable_rows_begin = ' "rows" : [';
|
||||
var strTable_rows_end = ']';
|
||||
var strCols = "";
|
||||
|
||||
var length = 0;
|
||||
for(var y in TV){// 获得 TV对象的 成员个数
|
||||
length++;
|
||||
}
|
||||
|
||||
var i = 1;
|
||||
for(var x in TV){// 初始化 strCols
|
||||
if(i >= cols){
|
||||
strCols += '"' + "TV." + x + '"' ;
|
||||
break;
|
||||
}else{
|
||||
strCols += '"' + "TV." + x + '"' + ',';
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 1;//控制循环 一行cols 后重置的计数
|
||||
var n = 1; //用于最后一次 不加 都好的 计数
|
||||
var m = 1; //用于跳过cols 部分的计数
|
||||
var strRowsUnit = "";
|
||||
var strRows = "";
|
||||
length = length - cols;
|
||||
for(var z in TV){
|
||||
if(m <= cols){//跳过 表格cols 部分
|
||||
m++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(i >= cols){
|
||||
strRowsUnit += '"' + "TV." + z + '"' ;
|
||||
i = 1;//重置i
|
||||
if(n < length){
|
||||
strRowsUnit = '[' + strRowsUnit + ']' + ',';
|
||||
}else if(n === length){
|
||||
strRowsUnit = '[' + strRowsUnit + ']';
|
||||
}
|
||||
strRows += strRowsUnit;
|
||||
strRowsUnit = "";//重置
|
||||
}else{
|
||||
strRowsUnit += '"' + "TV." + z + '"' + ',';
|
||||
i++;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
var tableString = strHead + srtTable_type + strTable_title + strTable_cols_begin + strCols + strTable_cols_end + strTable_rows_begin + strRows + strTable_rows_end + strEnd;
|
||||
return tableString;
|
||||
}
|
||||
$.UpdateLogStatus = function(msg) { //更新状态栏
|
||||
//列用ABC表示,行用0123表示
|
||||
ConnectDate(g_cols,g_rows);//链接数据
|
||||
LogStatus("当前时间:" + (new Date()) + "msg:" + msg + "\n" + "`" + JSON.stringify(objTable) + "`");//更新状态栏
|
||||
};
|
||||
//----------------------------------状态栏表格模块over-------------------------------------------------------
|
||||
//----------------------------------导出函数----------------------------------------------------------------
|
||||
$.SignOP = function(time,price,amount,state,message){//该函数作用是在策略运行时,在K线图表上标记“开多仓”,“开空仓”,“平仓” 的位置。
|
||||
//参数time: 在策略中使用此函数的时间,一般用(new Date()).getTime() , price:这个参数是在标签上显示 价格(多空平), amount:这个参数是在标签上显示 数量(成交) ,state: 这个参数是用来控制标记的类型,state = 1开多 ,2开空 ,0 平仓
|
||||
if(arguments.length < 4){
|
||||
Log("SignOP 函数 必须传入4个参数 : time、price、amount、state");
|
||||
return;
|
||||
}
|
||||
if(typeof(message) === "undefined"){
|
||||
message = "";
|
||||
}
|
||||
SignOP(time,price,amount,state,message);
|
||||
};
|
||||
$.Draw = function(records){
|
||||
Draw(records);
|
||||
};
|
||||
$.AddZhiBiao = function(zhibiao_Array,records,index){//该函数是在图表上添加指标线,zhibiao_Array:这个参数是指标数据(数组),records:产生指标数据的 原始K线数据,index:指标线的编号,从1开始递增
|
||||
if(records[records.length - 1].Time === lastRecordsTime){
|
||||
chart.add([index+1,[records[records.length - 1].Time,zhibiao_Array[zhibiao_Array.length - 1]],-1]);
|
||||
}else{
|
||||
chart.add([index+1,[records[records.length - 2].Time,zhibiao_Array[zhibiao_Array.length - 2]],-1]);
|
||||
chart.add([index+1,[records[records.length - 1].Time,zhibiao_Array[zhibiao_Array.length - 1]]]);
|
||||
//lastRecordsTime = records[records.length - 1].Time; //测试 取消
|
||||
}
|
||||
//chart.update(ChartObj); //测试取消
|
||||
};
|
||||
$.UpdateChart = function(records){//更新图表,每次添加指标线,添加标签 后需要更新 才有效。 records: K线原始数据
|
||||
if(records[records.length - 1].Time !== lastRecordsTime){
|
||||
lastRecordsTime = records[records.length - 1].Time;
|
||||
}
|
||||
chart.update(ChartObj);
|
||||
chart.reset(500);//默认 保留500个K线
|
||||
};
|
||||
//----------------------------------导出函数over-----------------------------------------------------------
|
||||
//测试
|
||||
function main(){
|
||||
///*测试图表功能
|
||||
var i = 0;
|
||||
var records = exchange.GetRecords();
|
||||
while(!records || records.length < 5){
|
||||
records = exchange.GetRecords();
|
||||
Sleep(500);
|
||||
}
|
||||
var zhibiao = [1,2,3,5,6,4,1,21,5];//ceshi
|
||||
var zhibiao2 = [11,22,44,57,8,77,5];
|
||||
|
||||
//$.SignOP((new Date()).getTime(),null,null,3,"自定义信息标记到图表上");// 测试标记 自定义信息 到图表上
|
||||
while(i < 500){
|
||||
Draw(records);
|
||||
if(i===20){
|
||||
//Sleep(60*60*1000);
|
||||
SignOP((new Date()).getTime(),2900,1,1);
|
||||
$.SignOP((new Date()).getTime(),null,null,3,"自定义信息标记到图表上");// 测试标记 自定义信息 到图表上
|
||||
}
|
||||
//zhibiao.shift();
|
||||
//zhibiao.push(zhibiao[zhibiao.length - 1] + 1);//ceshi
|
||||
//Log("ceshi"); //ceshi
|
||||
$.AddZhiBiao(zhibiao,records,1);
|
||||
//$.AddZhiBiao(zhibiao2,records,2);
|
||||
//Log("ceshi"); //ceshi
|
||||
|
||||
//Draw(records);
|
||||
//Log("ceshi1"); //ceshi
|
||||
Sleep(200);
|
||||
records = exchange.GetRecords();
|
||||
$.UpdateChart(records);//更新图表
|
||||
i++;
|
||||
}
|
||||
//*/
|
||||
/*测试状态栏表格功能*/
|
||||
var cols = 6;//列 设置一个变量 代表 列
|
||||
var rows = 4;//行 设置一个变量 代表 行
|
||||
$.TableInit(cols,rows); //初始化 状态栏 会显示 各个单元格的 坐标
|
||||
///*
|
||||
for(var x in TV){
|
||||
TV[x] = "lalala";// 全部单元格写成 lalala
|
||||
}
|
||||
//更新表格 显示 lalala, 表头 数据不能重复 ,否则显示不出来。
|
||||
/*
|
||||
TV.a0 = "a0";
|
||||
TV.b0 = "b0";
|
||||
TV.c0 = "c0";
|
||||
TV.d0 = "d0";
|
||||
TV.e0 = "e0";
|
||||
TV.f0 = "f0";//先把 表头数据写成不一样的
|
||||
*/
|
||||
$.UpdateLogStatus(cols,rows);//更新 状态栏表格
|
||||
|
||||
///*
|
||||
//怎么在 表格里面写入数据呢?
|
||||
var num = 100;
|
||||
var text = "文本:测试表格文本";
|
||||
var obj = {name:"对象",age:"19",sex:"girl"};
|
||||
var array = ["数组",22,33,54];
|
||||
TV.a1 = num;
|
||||
TV.c2 = text;
|
||||
TV.b3 = obj;
|
||||
TV.b0 = array;
|
||||
|
||||
$.UpdateLogStatus(cols,rows);//再次更新 状态栏表格
|
||||
//*/
|
||||
}
|
||||
/*修改
|
||||
1、增加了是否开启右边坐标轴
|
||||
2、增加参数 lineType : spline / line
|
||||
*/
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/36026
|
||||
策略名称: 图表界面信息展示实例1
|
||||
策略作者: 太极
|
||||
策略描述:
|
||||
|
||||
11111111
|
||||
|
||||
*/
|
||||
|
||||
//==========================================
|
||||
//API: Chart 函数使用的简单例子(画图功能)
|
||||
var chart = { // 这个 chart 在JS 语言中 是对象, 在使用Chart 函数之前我们需要声明一个配置图表的对象变量chart。
|
||||
__isStock: true, // 标记是否为一般图表,有兴趣的可以改成 false 运行看看。
|
||||
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'}, // 缩放工具
|
||||
title : { text : '差价分析图'}, // 标题
|
||||
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
|
||||
},
|
||||
xAxis: { type: 'datetime'}, // 坐标轴横轴 即:x轴, 当前设置的类型是 :时间
|
||||
yAxis : { // 坐标轴纵轴 即:y轴, 默认数值随数据大小调整。
|
||||
title:{text: '差价'}, // 标题
|
||||
opposite:false, // 是否启用右边纵轴
|
||||
},
|
||||
series : [ // 数据系列,该属性保存的是 各个 数据系列(线, K线图, 标签等..)
|
||||
{name:"交易所0",id:"0,Buy",color:'#FF3030',data:[]}, // 索引为0, data 数组内存放的是该索引系列的 数据
|
||||
{name:"交易所1",id:"1,Buy",dashStyle:'shortdash',data:[]}, // 索引为1,设置了dashStyle : 'shortdash' 即:设置 虚线。
|
||||
{name:"交易所2",id:"2,Buy",color:'#912CEE',data:[]},
|
||||
//RGB颜色对照表 http://www.114la.com/other/rgb.htm
|
||||
]
|
||||
};
|
||||
//==========================================
|
||||
//获取当前时间
|
||||
function getNowFormatDate() {
|
||||
var date = new Date();
|
||||
var seperator1 = "-";
|
||||
var seperator2 = ":";
|
||||
var month = date.getMonth() + 1;
|
||||
var strDate = date.getDate();
|
||||
if (month >= 1 && month <= 9) {
|
||||
month = "0" + month;
|
||||
}
|
||||
if (strDate >= 0 && strDate <= 9) {
|
||||
strDate = "0" + strDate;
|
||||
}
|
||||
var currentdate = date.getFullYear()+seperator1+month+seperator1+strDate+" "+date.getHours()+seperator2+date.getMinutes()+seperator2+date.getSeconds();
|
||||
return currentdate;
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
//==========================================
|
||||
//画图 https://www.botvs.com/bbs-topic/581
|
||||
var ObjChart = Chart(chart); // 调用 Chart 函数,初始化 图表。
|
||||
ObjChart.reset(); // 清空
|
||||
while(true){
|
||||
var nowTime = new Date().getTime(); //获取时间戳,
|
||||
var Buy_0 = _C(exchanges[0].GetTicker).Buy; //获取平台0行情数据 买一价
|
||||
var Buy_1 = _C(exchanges[1].GetTicker).Buy; //获取平台1行情数据 买一价
|
||||
var Buy_2 = _C(exchanges[2].GetTicker).Buy; //获取平台2行情数据 买一价
|
||||
ObjChart.add([0, [nowTime,Buy_0]]); // 用时间戳作为X值, 买一价 作为Y值 传入 索引0 的数据序列。
|
||||
ObjChart.add([1, [nowTime,Buy_1]]); // 同上。
|
||||
ObjChart.add([2, [nowTime,Buy_2]]); // 同上。
|
||||
ObjChart.update(chart); // 更新图表以显示出来。
|
||||
Sleep(2000);
|
||||
}
|
||||
//==========================================
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
'''
|
||||
策略出处: https://www.botvs.com/strategy/37664
|
||||
策略名称: 均线-趋势_数字货币策略V0.2 (Copy)
|
||||
策略作者: victoro
|
||||
策略描述:
|
||||
|
||||
@太极 QQ7650371
|
||||
#均线/趋势 策略
|
||||
#通过判断 在死叉下底后回弹多少买入
|
||||
#在金叉上扬至顶后下降多少卖出
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
-------------- ------------------------------------------------------------------------------ ------------------
|
||||
FastPeriod 2 开仓快线周期
|
||||
SlowPeriod 4 开仓慢线周期
|
||||
EnterPeriod true 开仓观察期
|
||||
x ------------------------------------------------------------------------------ 分割符号
|
||||
ExitFastPeriod 2 平仓快线周期
|
||||
ExitSlowPeriod 4 平仓慢线周期
|
||||
ExitPeriod 2 平仓观察期
|
||||
xx ------------------------------------------------------------------------------ 分割符号
|
||||
PositionRatio 0.5 仓位比例
|
||||
Interval 10 轮询周期(秒)
|
||||
xxx ------------------------------------------------------------------------------ 分割符号
|
||||
MAType 0 均线类型: TA.EMA|TA.MA
|
||||
'''
|
||||
|
||||
#!/usr/local/bin/python
|
||||
#-*- coding: UTF-8 -*-
|
||||
#均线/趋势 策略
|
||||
#通过判断 在死叉下底后回弹多少买入
|
||||
#在金叉上扬至顶后下降多少卖出
|
||||
|
||||
|
||||
# FastPeriod=3 #开仓快线周期
|
||||
# SlowPeriod=7 #开仓慢线周期
|
||||
# EnterPeriod=1 #开仓观察期
|
||||
# ExitFastPeriod=3 #平仓线周期
|
||||
# ExitSlowPeriod=7 #平仓慢线周期
|
||||
# ExitPeriod=2 #平仓观察期
|
||||
# PositionRatio=0.5 #仓位比例
|
||||
# Interval=10 #轮询周期
|
||||
# MAType=0 #均线类型 TA.EMA|TA.MA
|
||||
|
||||
|
||||
import types
|
||||
array = [TA.EMA,TA.MA]
|
||||
_MACalcMethod = array[MAType]
|
||||
def Cross(a,b): #计算均线方法
|
||||
crossNum = 0
|
||||
arr1 = []
|
||||
arr2 = []
|
||||
if(type(a) == types.ListType and type(b) == types.ListType):
|
||||
arr1 = a
|
||||
arr2 = b
|
||||
else:
|
||||
records = null
|
||||
while True:
|
||||
records = exchange.GetRecords()
|
||||
if(records and len(records) > a and len(records) > b):
|
||||
break
|
||||
Sleep(Interval)
|
||||
arr1 = _MACalcMethod(records,a)
|
||||
arr2 = _MACalcMethod(records,b)
|
||||
if(len(arr1) != len(arr2)):
|
||||
raise Exception("array length not equal")
|
||||
for i in range(len(arr1) - 1,-1,-1):
|
||||
if((type(arr1[i]) != types.IntType and type(arr1[i]) != types.FloatType) or (type(arr2[i]) != types.IntType and type(arr2[i]) != types.FloatType) ):
|
||||
break
|
||||
if(arr1[i] < arr2[i]):
|
||||
if(crossNum > 0):
|
||||
break
|
||||
crossNum -= 1
|
||||
elif(arr1[i] > arr2[i]):
|
||||
if(crossNum < 0):
|
||||
break
|
||||
crossNum += 1
|
||||
else:
|
||||
break
|
||||
return crossNum
|
||||
|
||||
import datetime
|
||||
def Caltime(date1,date2):
|
||||
try:
|
||||
date1=time.strptime(date1,"%Y-%m-%d %H:%M:%S")
|
||||
date2=time.strptime(date2,"%Y-%m-%d %H:%M:%S")
|
||||
date1=datetime.datetime(date1[0],date1[1],date1[2],date1[3],date1[4],date1[5])
|
||||
date2=datetime.datetime(date2[0],date2[1],date2[2],date2[3],date2[4],date2[5])
|
||||
return date2-date1
|
||||
except Exception,ex:
|
||||
Log('except Exception Caltime:',ex)
|
||||
return "except Exception"
|
||||
|
||||
import time
|
||||
start_timexx =time.localtime(time.time()) #time.clock()
|
||||
start_time=time.strftime("%Y-%m-%d %H:%M:%S",start_timexx)
|
||||
buy_price=0 #买入价格
|
||||
buy_qty=0 #买入数量
|
||||
gains=0 #盈利
|
||||
|
||||
def my_buy(): #开仓
|
||||
try:
|
||||
global buy_price,buy_qty
|
||||
initAccount = ext.GetAccount() #交易模板的导出函数, 获得账户状态,保存策略运行前账户初始状态
|
||||
opAmount=1
|
||||
#开仓之前判断有币没有没有先进行买入
|
||||
if int(initAccount.Stocks)>1:
|
||||
if buy_price<1:
|
||||
buy_price=_C(exchange.GetTicker).Last
|
||||
buy_qty=initAccount.Stocks
|
||||
Log('开仓信息1 仓内还有比:',initAccount.Stocks,'进行清空','--开仓详情:',initAccount)
|
||||
return 1
|
||||
if int(initAccount.Stocks)<1:
|
||||
if int(str(initAccount.Stocks).replace('0.',''))>=1:
|
||||
if buy_price<1:
|
||||
buy_price=_C(exchange.GetTicker).Last
|
||||
buy_qty=initAccount.Stocks
|
||||
Log('开仓信息2 仓内还有比:',initAccount.Stocks,'进行清空','--开仓详情:',initAccount)
|
||||
return 1
|
||||
|
||||
#if int(initAccount.Stocks)<1:
|
||||
if int(str(initAccount.Stocks).replace('0.',''))==0:
|
||||
#opAmount=1
|
||||
opAmount = _N(initAccount.Balance*PositionRatio,3) #买入数量
|
||||
Log("开仓没有币先进行 开仓买入%s元"%(str(opAmount))) #生成LOG日志
|
||||
# else:
|
||||
# opAmount = _N(initAccount.Stocks * PositionRatio,3) #获取交易数量
|
||||
# else:
|
||||
# opAmount = _N(initAccount.Stocks * PositionRatio,3) #获取交易数量
|
||||
Dict = ext.Buy(opAmount) #买入ext.Buy
|
||||
if(Dict):#确认开仓成功
|
||||
buy_price=Dict['price'] #买入价格 #{'price': 4046.446, 'amount': 1.5}
|
||||
buy_qty=Dict['amount'] #买入数量
|
||||
print_log(1,initAccount,Dict)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
except Exception,ex:
|
||||
Log('except Exception my_buy:',ex)
|
||||
return 0
|
||||
|
||||
outAccount = ext.GetAccount() #初始化信息
|
||||
def print_log(k_p,Account,Dict):
|
||||
try:
|
||||
global outAccount
|
||||
name=""
|
||||
if k_p:
|
||||
LogProfit(_N(gains,4),'开仓信息 钱:',Account.Balance,'--币:',Account.Stocks,'--开仓详情:',Dict)
|
||||
name="开仓"
|
||||
else:
|
||||
LogProfit(_N(gains,4),'平仓信息 钱:',Account.Balance,'--币:',Account.Stocks,'--平仓详情:',Dict)
|
||||
name="平仓"
|
||||
endAccount = ext.GetAccount() #初始化信息
|
||||
date1=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
|
||||
LogStatus("初始化投入2016/9/16 投入资金2000元\r\n",
|
||||
"本次初始化状态:",outAccount,
|
||||
"\r\n当前运 行状态:",endAccount,
|
||||
"\r\n本次开始运行时间:%s 已运行:%s\r\n"%(start_time,Caltime(start_time,date1)),
|
||||
"本次盈利:%s\r\n"%(str(gains)),
|
||||
"当前状态:%s--钱:%s--币:%s\r\n"%(str(name),str(Account.Balance),str(Account.Stocks)),
|
||||
"更新时间:%s"%(date1)
|
||||
) # 测试
|
||||
except Exception,ex:
|
||||
Log('except Exception print_log:',ex)
|
||||
|
||||
|
||||
def my_sell(): #平仓
|
||||
try:
|
||||
global buy_price,buy_qty,gains,start_time
|
||||
nowAccount = ext.GetAccount() #交易模板的导出函数 获取账户信息
|
||||
if _C(exchange.GetTicker).Last>buy_price+4: #当前价格一定要大于 开仓价格
|
||||
Dict = ext.Sell(nowAccount.Stocks)
|
||||
if(Dict):
|
||||
sell_gains=(Dict['price']-buy_price)*Dict['amount']
|
||||
gains=gains+sell_gains
|
||||
buy_price=0 #买入价格
|
||||
buy_qty=0 #买入数量
|
||||
print_log(0,nowAccount,Dict)
|
||||
return 1
|
||||
return 0
|
||||
except Exception,ex:
|
||||
Log('except Exception my_sell:',ex)
|
||||
return 0
|
||||
|
||||
def main():
|
||||
global outAccount
|
||||
STATE_IDLE = -1 #空闲状态
|
||||
state = STATE_IDLE #初始化 状态 为 空闲
|
||||
|
||||
Log("run ",outAccount) #输出初始账户信息
|
||||
SetErrorFilter("GetAccount|GetRecords|GetTicker") #屏蔽错误内容
|
||||
|
||||
b=0 #开仓
|
||||
b1=0 #检测次数
|
||||
a=0 #平仓
|
||||
a1=0 #检测次数
|
||||
while True:
|
||||
if(state == STATE_IDLE): #判断状态是否 为空闲 触发开仓
|
||||
#开仓
|
||||
n = Cross(FastPeriod,SlowPeriod) #模板函数获取EMA指标快线、慢线交叉结果
|
||||
if n<0: #确定当前为死叉
|
||||
b1+=1
|
||||
if b>=int(n): #说明现在还是在下跌涨趋势
|
||||
b=int(n)
|
||||
else: #开始下跌 开仓
|
||||
if(int(n)>=int(b)+int(EnterPeriod)): #确认上行走势 至自己定义的点
|
||||
if my_buy(): #开仓
|
||||
b=0
|
||||
b1=0
|
||||
state = PD_SHORT
|
||||
# if(b1>=10):#小波动操作开仓
|
||||
# b1=0
|
||||
# if my_buy():
|
||||
# b=0
|
||||
# state = PD_SHORT
|
||||
else:#平仓
|
||||
n = Cross(ExitFastPeriod,ExitSlowPeriod) #模板函数获取EMA指标快线、慢线交叉结果
|
||||
if n>0: #确定当前为金叉
|
||||
a1+=1
|
||||
if a<=int(n): #说明现在还是在上涨趋势
|
||||
a=int(n)
|
||||
else: #开始下跌 平仓
|
||||
if(int(n)<=int(a)-int(ExitPeriod)): #确认下行走势 至自己定义的点
|
||||
if my_sell(): #平仓
|
||||
a=0
|
||||
a1=0
|
||||
state = STATE_IDLE #更改状态 为空闲 触发开仓
|
||||
# if(a1>=10): #小波动操作平仓
|
||||
# a1=0
|
||||
# if my_sell():
|
||||
# a=0
|
||||
# state = STATE_IDLE #更改状态 为空闲 触发开仓
|
||||
Sleep(Interval * 1000)
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ isUse true 是否启用
|
||||
|
||||
/*参数
|
||||
*/
|
||||
|
||||
//功能函数
|
||||
var VirtualIndex = 0;
|
||||
var Originals = [];
|
||||
|
||||
@@ -126,11 +126,11 @@ function Trade(e, tradeType, tradeAmount, mode, slidePrice, maxAmount, maxSpace,
|
||||
var doAmount = 0;
|
||||
if (isBuy) {
|
||||
diffMoney = _N(initAccount.Balance - nowAccount.Balance, 4);
|
||||
dealAmount = _N(nowAccount.Stocks - initAccount.Stocks, 4);
|
||||
dealAmount = _N(nowAccount.Stocks - initAccount.Stocks, 8); // 如果保留小数过少,会引起在小交易量交易时,计算出的成交价格误差较大。
|
||||
doAmount = Math.min(maxAmount, tradeAmount - dealAmount, _N((nowAccount.Balance - 10) / tradePrice, 4));
|
||||
} else {
|
||||
diffMoney = _N(nowAccount.Balance - initAccount.Balance, 4);
|
||||
dealAmount = _N(initAccount.Stocks - nowAccount.Stocks, 4);
|
||||
dealAmount = _N(initAccount.Stocks - nowAccount.Stocks, 8);
|
||||
doAmount = Math.min(maxAmount, tradeAmount - dealAmount, nowAccount.Stocks);
|
||||
}
|
||||
if (doAmount < e.GetMinStock()) {
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/38203
|
||||
策略名称: 测试多图表展示
|
||||
策略作者: Zero
|
||||
策略描述:
|
||||
|
||||
BotVS支持策略同时展现多个图表, 这是一个简单的例子. 如果不能正常展示, 请清空浏览器缓存后刷新
|
||||
|
||||
*/
|
||||
|
||||
function main() {
|
||||
var cfgA = {
|
||||
title: {
|
||||
text: '盘口图表'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime'
|
||||
},
|
||||
series: [{
|
||||
name: '买一',
|
||||
data: [],
|
||||
},{
|
||||
name: '卖一',
|
||||
data: [],
|
||||
}]
|
||||
}
|
||||
var cfgB = {
|
||||
title: {
|
||||
text: '差价图'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime'
|
||||
},
|
||||
series: [{
|
||||
name: '差价',
|
||||
type: 'column',
|
||||
data: [],
|
||||
}]
|
||||
}
|
||||
|
||||
var chart = Chart([cfgA, cfgB]);
|
||||
chart.reset()
|
||||
while (true) {
|
||||
Sleep(1000)
|
||||
var ticker = exchange.GetTicker()
|
||||
if (!ticker) {
|
||||
continue;
|
||||
}
|
||||
var diff = ticker.Sell - ticker.Buy
|
||||
cfgA.subtitle = {
|
||||
text: '买一 ' + ticker.Buy + ', 卖一 ' + ticker.Sell,
|
||||
};
|
||||
cfgB.subtitle = {
|
||||
text: '价差 ' + diff,
|
||||
};
|
||||
// update相当于重置了图表的配置
|
||||
chart.update([cfgA, cfgB]);
|
||||
chart.add([0, [new Date().getTime(), ticker.Buy]]);
|
||||
chart.add([1, [new Date().getTime(), ticker.Sell]]);
|
||||
// 相当于更新第二个图表的第一个数据序列
|
||||
chart.add([2, [new Date().getTime(), diff]]);
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/35986
|
||||
策略名称: 转换任意K线周期
|
||||
策略作者: 小小梦
|
||||
策略描述:
|
||||
|
||||
示例策略
|
||||
- 转换基础K线为任意K线周期
|
||||
- 暂时不支持 秒级别
|
||||
测试版本,如有BUG ,问题 欢迎留言。
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
---------------- ------------ -------
|
||||
UI_NewCycleForMS 1000*60*60*2 合成周期毫秒数
|
||||
*/
|
||||
|
||||
// K线周期合成 扩展为 根据基础K线 合成 为任意周期。
|
||||
var cloneObj = function(obj) { // 深拷贝 对象函数
|
||||
var str, newobj = obj.constructor === Array ? [] : {};
|
||||
if (typeof obj !== 'object') {
|
||||
return;
|
||||
} else if (JSON) {
|
||||
str = JSON.stringify(obj); //系列化对象
|
||||
newobj = JSON.parse(str); //还原
|
||||
} else {
|
||||
for (var i in obj) {
|
||||
newobj[i] = typeof obj[i] === 'object' ?
|
||||
cloneObj(obj[i]) : obj[i];
|
||||
}
|
||||
}
|
||||
return newobj;
|
||||
};
|
||||
|
||||
var DAY = 0;
|
||||
var HOURS = 1;
|
||||
var MINUTES = 2;
|
||||
var isFirstFind = true;
|
||||
var FirstStamp = null;
|
||||
|
||||
function GetDHM(objTime, BaseCycle, NewCycleForMS){
|
||||
var ret = [];
|
||||
if(BaseCycle % (1000 * 60 * 60 * 24) === 0){
|
||||
ret[0] = objTime.getDate();
|
||||
ret[1] = DAY;
|
||||
}else if(BaseCycle % (1000 * 60 * 60) === 0){
|
||||
ret[0] = objTime.getHours();
|
||||
ret[1] = HOURS;
|
||||
}else if(BaseCycle % (1000 * 60) === 0){
|
||||
ret[0] = objTime.getMinutes();
|
||||
ret[1] = MINUTES;
|
||||
}
|
||||
if(NewCycleForMS % (1000 * 60 * 60 * 24) === 0){
|
||||
ret[2] = DAY;
|
||||
}else if(NewCycleForMS % (1000 * 60 * 60) === 0){
|
||||
ret[2] = HOURS;
|
||||
}else if(NewCycleForMS % (1000 * 60) === 0){
|
||||
ret[2] = MINUTES;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function SearchFirstTime(ret, BaseCycle, NewCycleForMS){
|
||||
if(ret[1] === DAY && ret[2] === DAY){
|
||||
var array_day = [];
|
||||
for(var i = 1 ; i < 29; i += (NewCycleForMS / BaseCycle)){
|
||||
array_day.push(i);
|
||||
}
|
||||
for(var j = 0 ; j < array_day.length; j++ ){
|
||||
if(ret[0] === array_day[j]){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}else if(ret[1] === HOURS && ret[2] === HOURS){
|
||||
var array_hours = [];
|
||||
for(var i = 0 ; i < 24; i += (NewCycleForMS / BaseCycle)){
|
||||
array_hours.push(i);
|
||||
}
|
||||
for(var j = 0 ; j < array_hours.length ; j++){
|
||||
if(ret[0] === array_hours[j]){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}else if(ret[1] === MINUTES && ret[2] === MINUTES){
|
||||
var array_minutes = [];
|
||||
for(var i = 0; i < 60; i += (NewCycleForMS / BaseCycle)){
|
||||
array_minutes.push(i);
|
||||
}
|
||||
for(var j = 0; j < array_minutes.length; j++){
|
||||
if(ret[0] === array_minutes[j]){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
throw "目标周期与基础周期不匹配!目标周期毫秒数:" + NewCycleForMS + " 基础周期毫秒数: " + BaseCycle;
|
||||
}
|
||||
}
|
||||
|
||||
function Calc_High(AssRecords, n, BaseCycle, NewCycleForMS){
|
||||
var max = AssRecords[n].High;
|
||||
for(var i = 1 ; i < NewCycleForMS / BaseCycle; i++){
|
||||
max = Math.max(AssRecords[n + i].High, max);
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
function Calc_Low(AssRecords, n, BaseCycle, NewCycleForMS){
|
||||
var min = AssRecords[n].Low;
|
||||
for(var i = 1 ; i < NewCycleForMS / BaseCycle; i++){
|
||||
min = Math.min(AssRecords[n + i].Low, min);
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
function AssembleRecords(records, NewCycleForMS) {
|
||||
var AssRecords = records.slice(0); // 深拷贝
|
||||
var AfterAssRecords = [];
|
||||
|
||||
if(!records || records.length < 2){
|
||||
throw (!records) ? "传入的records参数为 错误" + records : "基础K线长度小于2";
|
||||
}
|
||||
var BaseCycle = records[records.length - 1].Time - records[records.length - 2].Time;
|
||||
if(NewCycleForMS % BaseCycle !== 0){
|
||||
throw "目标周期‘" + NewCycleForMS + "’不是 基础周期 ‘" + BaseCycle + "’ 的整倍数,无法合成!";
|
||||
}
|
||||
if(NewCycleForMS / BaseCycle > records.length){
|
||||
throw "基础K线数量不足,请检查是否基础K线周期过小!";
|
||||
}
|
||||
|
||||
// 判断时间戳, 找到 基础K线 相对于 目标K线的起始时间。
|
||||
var objTime = new Date();
|
||||
for (var i = 0; i < AssRecords.length; i++) {
|
||||
objTime.setTime(AssRecords[i].Time);
|
||||
var ret = GetDHM(objTime, BaseCycle, NewCycleForMS);
|
||||
|
||||
if (isFirstFind === true && SearchFirstTime(ret, BaseCycle, NewCycleForMS) === true) {
|
||||
FirstStamp = AssRecords[i].Time;
|
||||
for (j = 0; j < i; j++) {
|
||||
AssRecords.shift(); // 把目标K线周期前不满足合成的数据排除。
|
||||
}
|
||||
isFirstFind = false;
|
||||
break; // 排除后跳出
|
||||
}else if(isFirstFind === false){
|
||||
if((AssRecords[i].Time - FirstStamp) % NewCycleForMS === 0){
|
||||
for (j = 0; j < i; j++) {
|
||||
AssRecords.shift(); // 把目标K线周期前不满足合成的数据排除。
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var BarObj = { // 定义一个 K线柱结构
|
||||
Time: 0,
|
||||
Open: 0,
|
||||
High: 0,
|
||||
Low: 0,
|
||||
Close: 0,
|
||||
Volume: 0,
|
||||
};
|
||||
var n = 0;
|
||||
for (n = 0; n < AssRecords.length - (NewCycleForMS / BaseCycle); n += (NewCycleForMS / BaseCycle)) { // 合成
|
||||
/*
|
||||
{
|
||||
Time :一个时间戳, 精确到毫秒,与Javascript的 new Date().getTime() 得到的结果格式一样
|
||||
Open :开盘价
|
||||
High :最高价
|
||||
Low :最低价
|
||||
Close :收盘价
|
||||
Volume :交易量
|
||||
}
|
||||
*/
|
||||
BarObj.Time = AssRecords[n].Time;
|
||||
BarObj.Open = AssRecords[n].Open;
|
||||
BarObj.High = Calc_High(AssRecords, n, BaseCycle, NewCycleForMS);
|
||||
BarObj.Low = Calc_Low(AssRecords, n, BaseCycle, NewCycleForMS);
|
||||
BarObj.Close = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Close;
|
||||
BarObj.Volume = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Volume;
|
||||
AfterAssRecords.push(cloneObj(BarObj));
|
||||
}
|
||||
|
||||
BarObj.Time = AssRecords[n - (NewCycleForMS / BaseCycle)].Time + NewCycleForMS; // 最后一根时间不能变,
|
||||
BarObj.Open = AssRecords[n].Open;
|
||||
BarObj.Close = AssRecords[AssRecords.length - 1].Close;
|
||||
BarObj.Volume = AssRecords[AssRecords.length - 1].Volume;
|
||||
var max = AssRecords[n].High;
|
||||
var min = AssRecords[n].Low;
|
||||
for(var index_n = n + 1 ;index_n < AssRecords.length; index_n++){
|
||||
max = Math.max(max, AssRecords[index_n].High);
|
||||
min = Math.min(min, AssRecords[index_n].Low);
|
||||
}
|
||||
BarObj.High = max;
|
||||
BarObj.Low = min;
|
||||
AfterAssRecords.push(cloneObj(BarObj));
|
||||
|
||||
return AfterAssRecords;
|
||||
}
|
||||
|
||||
function main() { // 测试代码
|
||||
var records = exchange.GetRecords();
|
||||
while (!records || records.length < 24) {
|
||||
records = exchange.GetRecords();
|
||||
}
|
||||
|
||||
// 处理界面参数, 如果写到自己的策略里面 可以参考下
|
||||
var Num_UI_NewCycleForMS = 1;
|
||||
var arrayNum = UI_NewCycleForMS.split("*");
|
||||
for(var indexNum = 0 ; indexNum < arrayNum.length ; indexNum++){
|
||||
Num_UI_NewCycleForMS = Num_UI_NewCycleForMS * Number(arrayNum[indexNum]);
|
||||
}
|
||||
Log("自定义周期毫秒时间为:", Num_UI_NewCycleForMS);
|
||||
|
||||
|
||||
while(true){
|
||||
records = _C(exchange.GetRecords);
|
||||
// Log("原始K线数据:长度", records.length, "数据:", records);
|
||||
records = AssembleRecords(records, Num_UI_NewCycleForMS); // 第一个参数是 基础K线, 第二个参数是 要转换的周期的 毫秒数, 1000 * 60 * 20 就是 转换为 20分钟
|
||||
// Log("转换后K线数据:长度", records.length, "数据:", records);
|
||||
$.PlotRecords(records, 'BTC');
|
||||
// throw "stop"; // ceshi
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user