This commit is contained in:
botvs
2017-03-19 18:18:17 +08:00
parent c3019f6709
commit d511b018d7
16 changed files with 1807 additions and 94 deletions
+192
View File
@@ -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);
}
}
+293
View File
@@ -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);
}
}
-83
View File
@@ -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
View File
@@ -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"){
+13 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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() {
+94
View File
@@ -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));
}
+346
View File
@@ -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
*/
+72
View File
@@ -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)
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}