TypeError: cannot read property ‘length’ of null duk_hobject_props.c:2258 WToneAndWTtwo __FIL 这个报错。
看了下应该是在WToneAndWTtwo 这个函数中出的错,读取了null值的名字叫length这个属性,也就是 一个变量 比如 var name = null; 然后我 读取了name.length ,于是整片代码的找有调用length的地方。为了解决这个错误还写了个 函数:
function isNullAndLog(arr,strArrName){//空数组报错
if(!arr){
Log("arr is:",arr,"name:",strArrName);
return true;
}
return false;
}
想,嘿嘿 !这下所有用到length的变量我都放进这个函数检测一下,有null的BUG绝对逃不了。改好代码,上机器人测试。 用的30分钟K线测试,擦~~竟然又 :
TypeError: cannot read property ‘length’ of null duk_hobject_props.c:2258 WToneAndWTtwo FILE:1315 报错
百思不得其解!!!耐心!出去转一圈换换脑子说不定就顿悟了!(Z大教我的)。溜了一圈,果真有效。 回来我就想到了,是不是调用的指标库 传入的参数是null了,指标库运行的时候出错了??动手实验,于是继续撸:
function isNullAndLog(arr,strArrName){//空数组报错
if(!arr){
Log("arr is:",arr,"name:",strArrName);
return true;
}
return false;
}
function main(){
if(typeof(x) === undefined ){
Log(typeof(x));
}
var aaa = null;
Log(isNullAndLog(aaa));
/*
while(!aaa || aaa.length < 9){
Log("while xunhuan");
Sleep(5000 * 1000);
}
*/
talib.EMA(aaa,5);
}
talib.EMA(aaa,5); 关键这句 aaa 是 null ,我故意设置的,传进去看看什么效果。 果然 报错了 TypeError: Cannot read property ‘length’ of null ~~OK 很可能就是这个问题了,继续修改代码。
另外还有个问题是之前的想到了现在记录下代码:
function DeleteNullEle(initArr){
var dealArr = [];
var initArrLen = initArr.length;
for(var i = 0,j = 0 ; i < initArrLen ; i++,j++){
//Log("initArr-",i,":",initArr[i]);//ceshi
if(initArr[i] === null || isNaN(initArr[i]) ){
j--;
//Log("i:",i);//ceshi
continue;
}
dealArr[j] = initArr[i];
}
//Log("dealArr:",dealArr);//ceshi
return dealArr;
}
加入这个函数,原因是 有些数组 是这样的 [NaN,NaN,NaN,22,3,56,78,4,23] 但是在 发明者量化 测试 用Log 函数输出的时候显示的是null,这个
让我迷茫了好长时间啊,大坑,必须记着,你看到是null 说不定就是NaN ,所以判断null 是判断不出来的。
还有一点,就是 这个 while(!aaa || aaa.length < 10){…} ,如果 aaa === null 的话, 为什么不报错,因为 在 || 这个操作符的表达式
中!aaa 为真 表达式恒为真,所以后面的 aaa.length 可能就没执行(这点貌似在学习 HTML 、CSS 、DOM 的时候见过,判断游览器
的一些API用过。)
另外应一个群友要求,帮修改了一下差价监控,其实就是加个检测差价范围,并且微信推送,很简单的。
if (diff != __lastDiff) {
//--------------------------------------------------------------------------------------------
if(openWeixin){
if( (diff <= price1 || diff >= price2 ) && off_on === true ){
Log("差价:"+diff+"微信推送@");
off_on = false;
Sleep(1000);
}else{
off_on = true;
Sleep(1000);
}
}
//---------------------------------------------------------------------------------------------
// add添加数据到series, 参数格式为[series序号, 数据];
__chart.add([0, [new Date().getTime(), diff]]);
__lastDiff = diff;
}
在代码虚线之间的就是加入的代码,很简单,可能还不完善。
这些天在学习期货的策略编写,这个比现货复杂点,(幸亏有Z大的期货交易模板,要不然写交易细节就够喝一壶了 >____< ! ),在学习期货的时候,首先要把基本的概念弄清楚, 比如:买开仓(做多),卖平仓(多头平仓),卖开仓(做空),买平仓(空头平仓)这些基本的要清楚。另外期货交易的API 也比现货的多且复杂点。盘点下也就API文档中的几个。
if (!manager) {//Z大写的商品期货模板类库,用来管理交易的对象(manager 初始时null)。不明白的可以去看源代码,QQ群共享有注释版。
if (_C(exchange.GetPosition).length > 0) {
throw "策略启动前不能有持仓.";
}
Log('交易平台:', exchange.GetName(), _C(exchange.GetAccount)); //输出当前交易所 信息
var insDetail = _C(exchange.SetContractType, ContractTypeName); // 用容错函数 _C ,容错调用 SetContractType函数 首先明确 设置交易的合约类型。
Log("合约", insDetail.InstrumentName, "一手", insDetail.VolumeMultiple, "份, 最大下单量", insDetail.MaxLimitOrderVolume, "保证金率:", insDetail.LongMarginRatio.toFixed(4), insDetail.ShortMarginRatio.toFixed(4), "交割日期", insDetail.StartDelivDate);
// 上面这个Log 显示出合约的一些信息,注意 在回测的时候,与实际运行的结果不一样,可以看图杠杆都是null,保证金率都是0,可以试试看。
manager = $.NewPositionManager(); // 这个生成管理者 对象
}
exchange.SetMarginLevel(10); //不支持 在这里我试着设置了一下杠杆试试,发现 显示 错误:Not support ,CTP商品期货 应该不能自己调整杠杆
var positions = exchange.GetPosition(); 在所有的操作前 ,我试着调用了一下 GetPosition 函数 获取一下持仓信息,显示的null
Log(positions[0]);
exchange.SetDirection("buy"); // 在所有的操作前需要设置 操作方向 ,这里设置 买开仓(做多)。
var id = exchange.Buy(1911,1); // 执行买入操作 下了一个 限价单, 有兴趣的同学 可以试试 市价单。(嘿嘿!自己动手记得牢)
positions = _C(exchange.GetPosition); //再获取下 持仓信息 看看
Log(positions); //有持仓信息了, 在上面 Buy的时候 有兴趣的同学 试试 用低价格 买入。 Buy(1000,1) 看看。
function main(){
for(var i = 0 ; i < 10 ; i++){
var b1 = 0;
var b2 = 0;
var b3 = 15;
while(b1 < 200){
var t2s1 = (new Date()).getTime();
b1++;
Sleep(b3);
var t2s6 = (new Date()).getTime();
b2 += (t2s6 - t2s1);
}
Log("Sleep()",b3,"MS",b1,"平均次数",b2/b1);
}
throw 2;
}
我回测了一下,发现Sleep 函数 在回测里 会运行1秒(前后时间差为 1000),然后这段测试代码的时间误差很大,但是用模拟盘跑的话,基本上误差在1毫秒以内。可能是回测系统属于沙盒模型,里面时间的运行算法导致的误差。模拟就误差很小(1毫秒内)。但是朋友说虽然模拟误差小了,但是和我跑的还是不一样。我个人感觉是托管着得问题(我们测试的代码一样),我的托管着是本机运行的,他的是在VPS 上的托管着。感觉是这个问题,但是也说不清。回头请教Z大。
-这个是日志。
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7f332c591cc9 m=2
goroutine 0 [idle]:
goroutine 1 [select, 207 minutes]:
从第一行看到线程生成失败,资源暂时不可用(不足)。大概看出应该是内存的问题,可能是内存不足引起的。 解决办法: 1、检查运行的机器人策略代码,有没有使用的资源没有释放,有没有使用多线程的API。 2、使用ulimit 命令检查托管者所在系统的限制(Linux)。 这篇博客可以看下: (博客地址)[http://smilejay.com/2012/04/fork_resource/] 3、关注系统内存使用量。
使用 ulimit -a 显示:
ulimit 命令的参数: -H 设置硬资源限制. -S 设置软资源限制. -a 显示当前所有的资源限制. -c size:设置core文件的最大值.单位:blocks -d size:设置数据段的最大值.单位:kbytes -f size:设置创建文件的最大值.单位:blocks -l size:设置在内存中锁定进程的最大值.单位:kbytes -m size:设置可以使用的常驻内存的最大值.单位:kbytes -n size:设置内核可以同时打开的文件描述符的最大值.单位:n -p size:设置管道缓冲区的最大值.单位:kbytes -s size:设置堆栈的最大值.单位:kbytes -t size:设置CPU使用时间的最大上限.单位:seconds -v size:设置虚拟内存的最大值.单位:kbytes -u <程序数目> 用户最多可开启的程序数目
遇到这个问题的朋友发现,错误过滤 函数也许是引起问题的原因,找到了导致托管者(内存不断膨胀)崩溃的原因了。原因是策略中 SetErrorFilter(“502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused”);函数 使用不当,该函数只需调用一次,不能写在循环结构中。上面的问题(内存不断膨胀)就是由于这个函数写在了onTick 函数中,onTick函数不断的循环调用,导致最终的崩溃。
说明: 这个函数主要用于API容错,比如exchange.GetAccount()函数,这样调用: _C(exchange.GetAccount); 注意函数名不加括号,如果容错的函数需要加参数就写在_C()函数的第二个参数,依次往后。 使用例子。
function main(){
var account = null;
var amount = 1;
var price = 2000;
account = exchange.GetAccount();
Log("_C 函数使用前 account :",account);
//exchange = null;
_C(exchange.Buy,price,amount);
//exchange.Buy(price,1);
account = exchange.GetAccount();
Log("_C 函数使用后 account :",account);
}
大概猜测_C 函数是这样的:
function ___C(functionName,p1){
functionName("执行需要容错的函数,传入的测试参数为:",p1);
Log("__C 容错函数启动,容错完毕");
}
function main(){
pstr = "测试参数--hello";
___C(Log,pstr);
}
执行结果:
function main(){
var pi = 3.1415926535897;
Log("使用_N函数 前pi:",pi);
var piOfDeal = _N(pi,2);
Log("使用_N函数后 pi:",piOfDeal);
}
执行结果:
function main(){
Log("totalYLMoney 初始赋值 0");
var totalYLMoney = 0;
Log("totalYLMoney 已赋, = ",totalYLMoney);
if(typeof(_G("totalYLMoney_save")) !== "object"){
totalYLMoney = _G("totalYLMoney_save");
Log("读取 totalYLMoney 本地数据库 名称为totalYLMoney_save 的值 赋给 totalYLMoney ");
}else{
totalYLMoney = 100.12546328765458;
_G("totalYLMoney_save",totalYLMoney.toString());
Log("记录 totalYLMoney 保存到本地数据库");
}
Log("totalYLMoney",totalYLMoney);
Log("typeof\(_G(\"totalYLMoney_save\"))",typeof(_G("totalYLMoney_save")));
}
上面的_G()函数测试代码需要在机器人上测试,回测不支持。测试方法,把程序部署在机器人上,第一次启动机器人, 机器人会记录100.12546328765458;这个值到全局字典"totalYLMoney_save"名称内,再次运行一次机器人,你会发现var totalYLMoney = 0,这个变量totalYLMoney初始化后,依然从字典中读取出了策略第一次运行时储存的值。
很多时候看到群中的新同学,询问策略盈亏的算法。一般来说处理方法就几种,这里发下简单一点的,思路也是由群中大神提供,在这里我负责阐述一下。
浮动利润就是: 按 (现在币 - 初始币)x 现在的价格 + (现在的钱 - 初始的钱)
举例说明:比如 ,初始币价10元/个, 账户开始有币5个, 钱100元。 在一定时间段内 我以平均15元/个的价格 买了3个币。 在这段时间末,币价涨到20元/个。此刻我的账户为:币8个,钱55元。那么我们按照上边的方法计算一下此时间段内交易的盈亏(做多方向,做空方向原理相同)。 Profit = (8 - 5)* 20 + (55 - 100) = 60 + (-45) = 15 这种计算方法 盈利为 15元。 (注意:此刻你的收益是浮动的,因为如果此刻币价大跌,也许你不仅没利润了,还会赔钱,当然赔钱也是浮动的,因为你这个时候的收益是跟随币价浮动的,原因是做多没平仓,落袋) 补充点,如果在币价20元/个的时候,平仓,即20元卖出这均价15元买的3个币,此刻账户为:币5个,钱115元。那么还是上面的算法: Profit = (5 - 5) * 20 + (115 - 100) = 15 , 收益仍然是15元 ,区别是 若不考虑初始持币贬值,这样收益就不随价格变动了。
账面利润 : (现在币 x 现在价格+现在钱) - (初始币 x 初始价格 + 初始钱)
还用上面的例子:比如 ,初始币价10元/个, 账户开始有币5个, 钱100元。 在一定时间段内 我以平均15元/个的价格 买了3个币。 在这段时间末,币价涨到20元/个。此刻我的账户为:币8个,钱55元。 Profit = (8 * 20 + 55) - (5 * 10 + 100) = 215 - 150 = 65 这种计算方法盈利是65元。同样我把均价15买来的3个币20元平仓卖出。此刻账户为:币5个,钱115,再次计算 Profit = (5 * 20 + 115) - (5 * 10 + 100) = 215 - 150 = 65 一样。
比较以上两种方法,一个收益15,一个收益65,其实不难看出。第一种方法忽略初始持币的贬值升值带来的盈亏。第二种算法则是计算盈亏时包括初始持币贬值升值产生的盈亏。 感觉账面利润的计算适用于结算资金 提钱离场。 浮动利润适用于在一段时间内通过交易产生的盈亏。(若干笔交易带来的盈亏) 这些是小小梦浅析的一些经验,如有错误,恳请大神留言指正,先言谢了 ^-^
先看看平台上的API 说明:
LogStatus(Msg); // 此信息不保存到日志列表里, 只更新当前机器人的状态信息, 在日志上方显示, 可多次调用, 更新状态
LogStatus('这是一个普通的状态提示');
LogStatus('这是一个红色字体的状态提示 #ff0000');
LogStatus('这是一个多行的状态信息\n我是第二行');
var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table)+'`'); // JSON序列化后两边加上`字符, 视为一个复杂消息格式(当前支持表格)
LogStatus('第一行消息\n`' + JSON.stringify(table)+'`\n第三行消息'); // 表格信息也可以在多行中出现
LogStatus('`' + JSON.stringify([table, table])+'`'); // 支持多个表格同时显示, 将以TAB显示到一组里
测试代码:
function main(){
var value1 = 99;
var value2 ="ceshi 01";
var table1 = { type : "table", title : "ceshi1", cols : ["列1","列2","列3"] , rows : [ ["abc","def","ghi"] , ["1","2","3"] ] };
var table2 = { type : "table", title : "ceshi2", cols : ["列1","列2","列3"] , rows : [ ["abc",value1,"ghi"] , [value2,"2","3"] ] };
LogStatus("测试文本1\n`" + JSON.stringify([table1,table2]) + "`");
}
第一张图可以看到 我们在 ceshi1 这个表格分页内,表格的数据格式就是 var table1 ,var table2 这两个声明过的变量。当然table1 表格内的内容全部都是固定的字符串。 需要注意的是 在 JSON.stringify([table1,table2]) 函数前后 要加上 “`” 这个。否则表格显示不出。 当然,我们用表格就要动态显示一些数据,总不能一直是固定的文本内容吧。 table2 这个分页内有2个测试数据, value1 、 value2 , 这两个数据。 新同学可以把代码复制下来,自己 试试,改改。这样记得比较牢固。
直接可以测试,我用了随机数模拟动态变化的收益率,用来在图表上显示收益率曲线。上代码:
var ChartObj = {//画图
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A',enabled:true,valueDecimals:2,valueSuffix:'%'}, //提示框 就是鼠标在线上时 显示的一个 框框 里面有一些内容,这里是设置提示框的格式
chart: { zoomType:'x',panning:true },//图表缩放
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
},
subtitle: {text: " 显示瞬时收益率 % "},//副标题
xAxis:{type: 'datetime'}, //设置 X轴 的数值为时间类型
yAxis: [{
title: {text: '收益率 %'},//标题
style: {color: '#4572A7'},//样式
//opposite: false //生成右边Y轴
}
],
series: [//系列
{name:'收益率',dataLables:{enabled:true,format:'{y} %'},type:'spline',yAxis:0,data:[]} //该图标只用到一条曲线 ,所以 只用设置一个数据序列
]
};
var chart = Chart(ChartObj); //初始化
function main(){ //测试用的主函数
chart.update(ChartObj); //更新
chart.reset(); //清空图表
var i = 0; //初始一个 i 值 , 后面循环用, 用来限制循环次数
var randomNum = 0; //声明一个 随机数 初始化 0
while(i < 5000){ //限制循环次数
randomNum = Math.random() * 10; // 生产随机数 0 - 9.9999
//chart.add([0,[(new Date()),randomNum]]);
chart.add(0,[(new Date()).getTime(),randomNum + 5]); //把生成的随机数 按照时间(X 坐标) 把随机数 画在图表上(Y坐标)
Sleep(1000*60); // 程序 每次循环暂停60秒
//chart.update(ChartObj);
//chart.reset(500);
}
Log("over");
}
liuxinghui 小小梦老师,请教一下,下单后有未完成的订单要全部取消掉,应该怎么弄?
louis 这个必须赞一个!
凄凉雨 好东西....很多东西API文档并没有说出来..赞一个
叶落知秋 谢梦总整理的好东西
短线王赢出售高价策略 好东西!
小小梦 客气啦~ https://dn-filebox.qbox.me/bf52888dc68aba5326c403f2280994e81fbce2ee.png 教程 链接 : https://www.botvs.com/bbs-topic/475
小小梦 方便大家学习!嘿嘿!