update
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
策略出处: 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)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,913 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/34878
|
||||
策略名称: OKCoin期货跨期对冲策略
|
||||
策略作者: 小小梦
|
||||
策略描述:
|
||||
|
||||
OKCoin期货跨期对冲策略,季度、当周、次周
|
||||
- 1、 季度-当周
|
||||
- 2、 季度-次周
|
||||
- 3、 当周-次周
|
||||
- 4、在周五交割前5分钟会自动 平仓, 锁定15分钟 后再正常运行。
|
||||
|
||||
BUG:
|
||||
在期货策略中 不能使用 Go函数 ,会导致切换合约问题, 对此 策略已经修改,改为一般调用。
|
||||
支持限价单模式。
|
||||
市价单模式有一些问题。
|
||||
如有BUG 请回复 QQ: 359706687 小小梦, 及时更新!
|
||||
#### 测试有部分问题,持续更新中。
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
----------------- -------------------------- ---------------
|
||||
HedgeTable (this_week&quarter)30:15:1 对冲控制表
|
||||
isCreateHedgeList false 是否生成 对冲表(只支持1组)
|
||||
begin 10 起始差价
|
||||
end 300 结束差价
|
||||
size 10 网眼大小
|
||||
step 20 网格节点间距
|
||||
amountOfPoint true 节点下单量
|
||||
symbolA this_week 合约A
|
||||
symbolB quarter 合约B
|
||||
istry false 是否为回测模式 或者 实盘测试
|
||||
isFilter true 是否过滤常规错误
|
||||
For_USD false 显示为 美元 计价
|
||||
MarginLevel 10 杠杆
|
||||
MarginRatio 0.5 保证金占总 资金的比例
|
||||
AutoRecoveryState true 自动恢复
|
||||
Interval 500 轮询间隔
|
||||
isUseMarketOrder false 是否使用市价单
|
||||
*/
|
||||
|
||||
//2017.2.22
|
||||
/* 临时参数
|
||||
1、合约1 最大开仓量
|
||||
2、合约2 最大开仓量
|
||||
3、ATR 系数
|
||||
4、ATR 柱数
|
||||
5、ATR 更新周期(秒)
|
||||
6、样本数量
|
||||
7、样本采集轮询比例
|
||||
8、触发线调整周期(秒)
|
||||
9、合约1 杠杆参数
|
||||
10、合约2 杠杆参数
|
||||
11、合约1 字符串
|
||||
12、合约2 字符串
|
||||
13、盘口扫描深度
|
||||
14、轮询周期
|
||||
15、正对冲 开仓
|
||||
16、正对冲 平仓
|
||||
17、反对冲 开仓
|
||||
18、反对冲 平仓
|
||||
// 控制开关
|
||||
19、是否开启自动触发控制
|
||||
20、是否开启 交易控制表
|
||||
21、是否开启常规错误过滤
|
||||
22、是否开启回测 模式
|
||||
*/
|
||||
var checkTime = 0;
|
||||
var residualTime = 0;
|
||||
var checkPreTime = 0;
|
||||
var JGDate = []; // 交割模拟。 ["BTC1129", "BTC1229", "BTC0316"];
|
||||
var JGDateIndex = 0; // 模拟交割索引。
|
||||
var JGHoursCorrect = 8; // 检测交割剩余小时,在实盘中需要修正 8小时。 模拟时该值设置为0
|
||||
var idA = null;
|
||||
var idB = null;
|
||||
var A = 1;
|
||||
var B = 2;
|
||||
var PRE = 3;
|
||||
var PLUS = 4;
|
||||
var MINUS = 5;
|
||||
var FREE = 6;
|
||||
|
||||
function init(){
|
||||
if(istry){
|
||||
JGHoursCorrect = 0; // 模拟中 该值修改为0
|
||||
Log("启用模拟 交割,初始化交割日期列表。");
|
||||
UpdateJGDate();
|
||||
}
|
||||
}
|
||||
|
||||
function UpdateJGDate(){
|
||||
// 循环31次 遍历出 当前月份的所有 星期5的 日期, 取时间戳, 对比当前时间戳,小于当前的 丢弃,大于当前的第一个即是
|
||||
// 在用时间戳恢复日期,拿到 字符串
|
||||
var array_JG_stamp = [];
|
||||
var date = new Date();
|
||||
var nowStamp = date.getTime();
|
||||
var nowMonth = date.getMonth();
|
||||
var nextJG_Stamp = 0;
|
||||
date.setHours(16); // 0~23
|
||||
date.setMinutes(0); // 0~59
|
||||
date.setSeconds(0); // 0~59
|
||||
for(var i = 1 ; i <= 31; i++){
|
||||
date.setDate(i);
|
||||
var EveryDay = date.getDay(); // 1~6
|
||||
if(EveryDay === 5 && nowMonth == date.getMonth()){
|
||||
var fridayStamp = date.getTime();
|
||||
array_JG_stamp.push(fridayStamp);
|
||||
}
|
||||
}
|
||||
for(var j = 0 ; j < array_JG_stamp.length ; j++){
|
||||
if(nowStamp <= array_JG_stamp[j]){
|
||||
nextJG_Stamp = array_JG_stamp[j];
|
||||
break;
|
||||
}
|
||||
if(j == array_JG_stamp.length - 1){
|
||||
nextJG_Stamp = array_JG_stamp[j] + 1000 * 7 * 24 * 60 * 60;
|
||||
}
|
||||
}
|
||||
array_JG_stamp = [];
|
||||
for(var n = 1 ; n <= 100; n++){ // 生成 100 个 模拟交割日期。
|
||||
if(n == 1){
|
||||
array_JG_stamp.push(nextJG_Stamp);
|
||||
}else{
|
||||
nextJG_Stamp += 1000 * 7 * 24 * 60 * 60;
|
||||
array_JG_stamp.push(nextJG_Stamp);
|
||||
}
|
||||
}
|
||||
var date2 = new Date();
|
||||
for(var m = 0 ; m < array_JG_stamp.length ; m++){
|
||||
date2.setTime(array_JG_stamp[m]);
|
||||
var strMonth = date2.getMonth() + 1;
|
||||
var strDate = date2.getDate();
|
||||
if(strMonth < 10){
|
||||
strMonth = '0' + strMonth;
|
||||
}
|
||||
if(strDate < 10){
|
||||
strDate = '0' + strDate;
|
||||
}
|
||||
JGDate.push("BTC" + strMonth + strDate);
|
||||
}
|
||||
Log("模拟生成的交割日期:", JGDate);
|
||||
}
|
||||
|
||||
function CheckDelivery(nowTime, Symbol, task) {
|
||||
var contractInfo = null;
|
||||
if(checkTime <= 0){
|
||||
var contractName = "";
|
||||
var ContractIndex = 0;
|
||||
if(Symbol === "this_week"){
|
||||
ContractIndex = 0;
|
||||
}else if(Symbol === "next_week"){
|
||||
ContractIndex = 1;
|
||||
}else if(Symbol === "quarter"){
|
||||
ContractIndex = 2;
|
||||
}
|
||||
if(istry === true){ // 判断是不是 模拟测试
|
||||
try{
|
||||
contractName = JGDate[JGDateIndex]; // 模拟测试 交割日期
|
||||
JGDateIndex++;
|
||||
} catch(e){
|
||||
Log("回测模式,更新交割日期错误", e);
|
||||
JGDateIndex--;
|
||||
}
|
||||
}
|
||||
while (contractName == "") {
|
||||
//var contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=this_week"); //只是检测this_week ,避免重复调用提高效率
|
||||
switch(ContractIndex){
|
||||
case 0: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=this_week");
|
||||
break;
|
||||
case 1: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=next_week");
|
||||
break;
|
||||
case 2: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=quarter");
|
||||
break;
|
||||
default: Log("contractInfo:", contractInfo);
|
||||
//throw "switch NumContractType Error!";
|
||||
} //根据 contractType 类型 选择读取合约交割日期
|
||||
if (!contractInfo || contractInfo.length === 0) {
|
||||
Sleep(100);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
contractName = (JSON.parse(contractInfo))[0].contract_name;
|
||||
} catch (e) {
|
||||
Log("CheckDelivery Error",contractInfo, e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
var nowDateTime = new Date();
|
||||
contractName = contractName.split("BTC")[1]; //抽取BTC后的字符串 重新赋值
|
||||
var strMonth = contractName[0] + contractName[1];
|
||||
var strDay = contractName[2] + contractName[3];
|
||||
var strYear = nowDateTime.getFullYear() + ""; //获取 年份字符串
|
||||
|
||||
// 处理跨年问题
|
||||
var nowMonth = nowDateTime.getMonth(); // 获取月份
|
||||
if(strMonth < nowMonth){
|
||||
strYear = (strYear - 0) + 1;
|
||||
strYear = strYear + "";
|
||||
}
|
||||
|
||||
var strDate = strYear + '-' + strMonth + '-' + strDay + ' ' + "16:00:00";
|
||||
var deliveryTime = (new Date(strDate)).getTime(); // + 16 * 60 * 60 * 1000;
|
||||
nowTime = nowDateTime.getTime();
|
||||
residualTime = (deliveryTime - nowTime) / 1000 / 60 / 60 - JGHoursCorrect; //单位是小时
|
||||
checkTime = (deliveryTime - nowTime) - JGHoursCorrect * 1000 * 60 * 60; //还差多少毫秒交割
|
||||
checkPreTime = nowTime; //记录开始的时间
|
||||
Log("合约", Symbol, "交割日期获取:", strDate);
|
||||
}else{
|
||||
checkTime -= nowTime - checkPreTime; //减去消耗的时间
|
||||
checkPreTime = nowTime;
|
||||
residualTime = checkTime / 1000 / 60 / 60; // 计算距离交割多少小时
|
||||
}
|
||||
if(residualTime < 24){ //交割小于24小时
|
||||
MSG_String = " " + Symbol + " 交割时间剩余:" + residualTime + "小时!!#FF0000";
|
||||
if((checkTime / 1000 / 60) <= 5 && task.isFrozen == false){ // 每次交割前5分钟 锁定。
|
||||
Log("距离交割剩余5分钟,平掉所有仓位!#FF0000");
|
||||
for(var index = 0; index < task.dic.length; index++){
|
||||
if(task.dic[index].hold > 0){ // 平空A 平多B
|
||||
task.action = [index, "closesell", "closebuy", task.dic[index].hold];
|
||||
Log(JSON.stringify(task.action));
|
||||
Hedge_Open_Cover(task);
|
||||
$.PlotFlag(nowTime, "C", "closesell-closebuy", "circlepin");
|
||||
}else if(task.dic[index].hold < 0){ // 平多A 平空B
|
||||
task.action = [index, "closebuy", "closesell", task.dic[index].hold];
|
||||
Log(JSON.stringify(task.action));
|
||||
Hedge_Open_Cover(task);
|
||||
$.PlotFlag(nowTime, "C", "closebuy-closesell", "circlepin");
|
||||
}
|
||||
}
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition);
|
||||
UpdatePosition(task, Positions);
|
||||
Log("全部仓位已平,检查持仓:", Positions, "程序冻结15分钟!#FF0000");
|
||||
task.isFrozen = true;
|
||||
task.FrozenStartTime = new Date().getTime();
|
||||
}
|
||||
}else{
|
||||
MSG_String = " " + Symbol + " 交割时间剩余:" + residualTime + "小时!!";
|
||||
}
|
||||
return _N(residualTime, 3);
|
||||
}
|
||||
|
||||
|
||||
function OpenPriceToActual(Price, Piece){
|
||||
var OnePieceEquivalentCoin = 100 / Price;
|
||||
var OpenFee = Piece * (OnePieceEquivalentCoin) * (0.03 * 0.01);
|
||||
var Actual = Price + (OpenFee * Price) / (OnePieceEquivalentCoin * Piece);
|
||||
return Actual;
|
||||
//Log("Actual:", Actual, "OpenFee:", OpenFee, "OnePieceEquivalentCoin:", OnePieceEquivalentCoin, "保证金:", OpenFee / 0.01 / 0.03 / 10); // 测试
|
||||
//var Actual = Price + ((0.03 * 0.01) * Price);
|
||||
}
|
||||
|
||||
function CreateHedgeList(Begin, End, Size, Step, AmountOfPoint, SymbolA, SymbolB){
|
||||
// "(this_week&quarter)100:90:1;110:100:1;120:110:1;130:120:1;140:130:1;150:140:1;160:150:1;170:160:1;180:170:1;190:180:1";
|
||||
if((SymbolA !== "this_week" && SymbolA !== "next_week" && SymbolA !== "quarter") || (SymbolB !== "this_week" && SymbolB !== "next_week" && SymbolB !== "quarter")){
|
||||
throw "合约代码错误: SymbolA " + SymbolA + " SymbolB " + SymbolB;
|
||||
}
|
||||
var BodyString = "";
|
||||
var HeadString = '(' + SymbolA + '&' + SymbolB + ')';
|
||||
for(var i = Begin ; i <= End ; i += Step){
|
||||
if(i + Step > End){
|
||||
BodyString += (i + ':') + (i - Size) + (':' + AmountOfPoint);
|
||||
}else{
|
||||
BodyString += (i + ':') + (i - Size) + (':' + AmountOfPoint) + ';';
|
||||
}
|
||||
}
|
||||
var HL = HeadString + BodyString;
|
||||
Log("按参数生成对冲列表:", HL);
|
||||
return HL;
|
||||
}
|
||||
|
||||
function UpdatePosition(task, Positions, onlyAorBorPRE){
|
||||
if(Positions.length > 2){
|
||||
Log(Positions, "Positions 长度大于2!#FF0000");
|
||||
throw "同类型合约不能同时持有多仓空仓。";
|
||||
}
|
||||
if(onlyAorBorPRE == PRE){
|
||||
task.Pre_APositions = task.APositions;
|
||||
task.Pre_BPositions = task.BPositions;
|
||||
}
|
||||
for(var i = 0; i < Positions.length; i++){
|
||||
if(Positions[i].ContractType == task.symbolA && onlyAorBorPRE !== B){
|
||||
task.APositions = Positions[i];
|
||||
}
|
||||
if(Positions[i].ContractType == task.symbolB && onlyAorBorPRE !== A){
|
||||
task.BPositions = Positions[i];
|
||||
}
|
||||
}
|
||||
if(Positions.length == 0){
|
||||
if(onlyAorBorPRE !== B){
|
||||
task.APositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};
|
||||
}
|
||||
if(onlyAorBorPRE !== A){
|
||||
task.BPositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};
|
||||
}
|
||||
if(onlyAorBorPRE !== A && onlyAorBorPRE !== B){
|
||||
task.APositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};
|
||||
task.BPositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DealAction(task, AorB, amount){
|
||||
if(amount <= 0){
|
||||
throw "错误: DealAction 的 amount 参数为:" + amount;
|
||||
}
|
||||
if(AorB == A){
|
||||
task.e.SetContractType(task.symbolA);
|
||||
task.e.SetDirection(task.action[1]);
|
||||
if(task.action[1] == "buy" || task.action[1] == "closesell"){
|
||||
idA = task.e.Buy(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolA);
|
||||
}else if(task.action[1] == "sell" || task.action[1] == "closebuy"){
|
||||
idA = task.e.Sell(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolA);
|
||||
}
|
||||
}
|
||||
if(AorB == B){
|
||||
task.e.SetContractType(task.symbolB);
|
||||
task.e.SetDirection(task.action[2]);
|
||||
if(task.action[2] == "buy" || task.action[2] == "closesell"){
|
||||
idB = task.e.Buy(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolB);
|
||||
}else if(task.action[2] == "sell" || task.action[2] == "closebuy"){
|
||||
idB = task.e.Sell(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DealActionLimit(task, AorB, Piece, isAgain){
|
||||
var tradeInfo = null;
|
||||
var Price = 0;
|
||||
var Piece = Math.abs(Piece);
|
||||
if(isAgain){
|
||||
while(true){
|
||||
task.e.SetContractType(task.symbolA);
|
||||
var Adepth = task.e.GetDepth();
|
||||
task.e.SetContractType(task.symbolB);
|
||||
var Bdepth = task.e.GetDepth();
|
||||
|
||||
if(!Adepth || !Bdepth || Adepth.Asks.length === 0 || Adepth.Bids.length === 0 || Bdepth.Asks.length === 0 || Bdepth.Bids.length === 0){
|
||||
//Log("获取深度信息异常!", Adepth, Bdepth);
|
||||
Sleep(Interval);
|
||||
continue;
|
||||
}
|
||||
|
||||
task.Adepth = Adepth;
|
||||
task.Bdepth = Bdepth;
|
||||
|
||||
task.Adiff = _N(Adepth.Bids[0].Price - Bdepth.Asks[0].Price);
|
||||
task.Bdiff = _N(Adepth.Asks[0].Price - Bdepth.Bids[0].Price);
|
||||
break;
|
||||
}
|
||||
}
|
||||
task.e.SetContractType(AorB == A ? task.symbolA : task.symbolB);
|
||||
task.e.SetDirection(task.action[AorB]);
|
||||
if(task.action[AorB] == "buy"){
|
||||
Price = AorB == A ? task.Adepth.Asks[0].Price : task.Bdepth.Asks[0].Price;
|
||||
tradeInfo = task.P.OpenLong(AorB == A ? task.symbolA : task.symbolB, Piece, Price);
|
||||
}else if(task.action[AorB] == "sell"){
|
||||
Price = AorB == A ? task.Adepth.Bids[0].Price : task.Bdepth.Bids[0].Price;
|
||||
tradeInfo = task.P.OpenShort(AorB == A ? task.symbolA : task.symbolB, Piece, Price);
|
||||
}else if(task.action[AorB] == "closebuy"){
|
||||
Price = AorB == A ? task.Adepth.Bids[0].Price : task.Bdepth.Bids[0].Price;
|
||||
tradeInfo = task.P.Cover(AorB == A ? task.symbolA : task.symbolB, Price, Piece, PD_LONG); // task.action[AorB]
|
||||
}else if(task.action[AorB] == "closesell"){
|
||||
Price = AorB == A ? task.Adepth.Asks[0].Price : task.Bdepth.Asks[0].Price;
|
||||
tradeInfo = task.P.Cover(AorB == A ? task.symbolA : task.symbolB, Price, Piece, PD_SHORT); // task.action[AorB]
|
||||
}
|
||||
if((task.action[AorB] == "buy" || task.action[AorB] == "sell") && tradeInfo.amount === 0){
|
||||
return false;
|
||||
}else if((task.action[AorB] == "closebuy" || task.action[AorB] == "closesell") && tradeInfo == 0){
|
||||
return false;
|
||||
}
|
||||
return tradeInfo;
|
||||
}
|
||||
|
||||
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
|
||||
var tradeInfo_A = DealActionLimit(task, A, task.action[3]);
|
||||
var dealAmount_A = Math.abs(task.action[3]);
|
||||
while(tradeInfo_A == false || (dealAmount_A -= tradeInfo_A.amount) !== 0){
|
||||
Log("合约:" + task.symbolA + "已对冲" + (tradeInfo_A == false ? 0 : tradeInfo_A.amount), "剩余,重试!张数:" + dealAmount_A);
|
||||
tradeInfo_A = DealActionLimit(task, A, dealAmount_A, true);
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
var tradeInfo_B = DealActionLimit(task, B, task.action[3]);
|
||||
var dealAmount_B = Math.abs(task.action[3]);
|
||||
while(tradeInfo_B == false || (dealAmount_B -= tradeInfo_B.amount) !== 0){
|
||||
Log("合约:" + task.symbolB + "已对冲" + (tradeInfo_B == false ? 0 : tradeInfo_B.amount), "剩余,重试!张数:" + dealAmount_B);
|
||||
tradeInfo_B = DealActionLimit(task, B, dealAmount_B, true);
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
task.dic[task.action[0]].hold = task.action[3];
|
||||
// task.dic[task.action[0]].ActualPrice = _N(orderA.AvgPrice - orderB.AvgPrice);
|
||||
}else if((task.action[1] === "closesell" && task.action[2] === "closebuy") || (task.action[1] === "closebuy" && task.action[2] === "closesell")){ // cover
|
||||
var tradeInfo_A_Piece = DealActionLimit(task, A, task.action[3]);
|
||||
var dealAmount_A = Math.abs(task.action[3]);
|
||||
while(tradeInfo_A_Piece == false || (dealAmount_A -= tradeInfo_A_Piece) !== 0){
|
||||
Log("合约:" + task.symbolA + "已对冲" + (tradeInfo_A == false ? 0 : tradeInfo_A_Piece), "剩余,重试!张数:" + dealAmount_A);
|
||||
tradeInfo_A_Piece = DealActionLimit(task, A, dealAmount_A, true);
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
var tradeInfo_B_Piece = DealActionLimit(task, B, task.action[3]);
|
||||
var dealAmount_B = Math.abs(task.action[3]);
|
||||
while(tradeInfo_B_Piece == false || (dealAmount_B -= tradeInfo_B_Piece) !== 0){
|
||||
Log("合约:" + task.symbolB + "已对冲" + (tradeInfo_B == false ? 0 : tradeInfo_B_Piece), "剩余,重试!张数:" + dealAmount_B);
|
||||
tradeInfo_B_Piece = DealActionLimit(task, B, dealAmount_B, true);
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
task.dic[task.action[0]].hold = 0;
|
||||
task.dic[task.action[0]].ActualPrice = 0;
|
||||
task.dic[task.action[0]].CoverTimes += 1;
|
||||
}
|
||||
Sleep(100);
|
||||
}else if(task.isUseMarketOrder === true){ // 市价单
|
||||
var orderA = null;
|
||||
var orderB = null;
|
||||
if((task.action[1] === "buy" && task.action[2] === "sell") || (task.action[1] === "sell" && task.action[2] === "buy")){ // open
|
||||
DealAction(task, A);
|
||||
DealAction(task, B);
|
||||
|
||||
while(!idA || !idB){
|
||||
if(!idA){
|
||||
DealAction(task, A);
|
||||
}
|
||||
if(!idB){
|
||||
DealAction(task, B);
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
if(!orderA || orderA.Status !== ORDER_STATE_CLOSED){
|
||||
orderA = task.e.GetOrder(idA);
|
||||
}
|
||||
if(!orderB || orderB.Status !== ORDER_STATE_CLOSED){
|
||||
orderB = task.e.GetOrder(idB);
|
||||
}
|
||||
if(orderA && orderB && orderA.Status == ORDER_STATE_CLOSED && orderB.Status == ORDER_STATE_CLOSED){
|
||||
break;
|
||||
}
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
//Log("Open symbolA:", orderA, "symbolB:", orderB);
|
||||
task.dic[task.action[0]].hold = task.action[3];
|
||||
task.dic[task.action[0]].ActualPrice = _N(orderA.AvgPrice - orderB.AvgPrice);
|
||||
}else if((task.action[1] === "closesell" && task.action[2] === "closebuy") || (task.action[1] === "closebuy" && task.action[2] === "closesell")){ // cover
|
||||
DealAction(task, A);
|
||||
DealAction(task, B);
|
||||
|
||||
while(!idA || !idB){
|
||||
if(!idA){
|
||||
DealAction(task, A);
|
||||
}
|
||||
if(!idB){
|
||||
DealAction(task, B);
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
if(!orderA || orderA.Status !== ORDER_STATE_CLOSED){
|
||||
orderA = task.e.GetOrder(idA);
|
||||
}
|
||||
if(!orderB || orderB.Status !== ORDER_STATE_CLOSED){
|
||||
orderB = task.e.GetOrder(idB);
|
||||
}
|
||||
if(orderA && orderB && orderA.Status == ORDER_STATE_CLOSED && orderB.Status == ORDER_STATE_CLOSED){
|
||||
break;
|
||||
}
|
||||
Sleep(Interval);
|
||||
}
|
||||
|
||||
//Log("Cover symbolA:", orderA, "symbolB:", orderB);
|
||||
task.dic[task.action[0]].hold = 0;
|
||||
task.dic[task.action[0]].ActualPrice = 0;
|
||||
task.dic[task.action[0]].CoverTimes += 1;
|
||||
}
|
||||
Sleep(100); // 避免访问过于频繁。
|
||||
}
|
||||
}
|
||||
|
||||
function TasksController(){ // 任务控制器 构造函数
|
||||
// 构造用于返回的 控制器对象
|
||||
var self = {};
|
||||
self.tasks = []; // 控制器的任务数组。
|
||||
|
||||
self.AddTask = function(e, symbolA, symbolB, HedgeList){ // 添加对冲 任务, 函数中进行 构造, 部分参数变量未初始化。在main 函数开始 根据界面参数列表,确定task 个数 进行构造。
|
||||
var task = {
|
||||
// 任务的参数变量
|
||||
e : e,
|
||||
symbolA : symbolA,
|
||||
symbolB : symbolB,
|
||||
HedgeList : HedgeList,
|
||||
dic : [],
|
||||
Adepth : null,
|
||||
Bdepth : null,
|
||||
Adiff : 0,
|
||||
Bdiff : 0,
|
||||
action : null,
|
||||
lastUpdateLineTime : 0,
|
||||
MarginLevel : MarginLevel,
|
||||
isUseMarketOrder : true,
|
||||
// 账户信息
|
||||
initAccount : _C(e.GetAccount),
|
||||
nowAccount : null,
|
||||
isFrozen : false,
|
||||
FrozenStartTime : 0,
|
||||
APositions : null,
|
||||
BPositions : null,
|
||||
PositionsLastUpdateTime : 0,
|
||||
isLogProfit : false,
|
||||
taskProfit : 0,
|
||||
State : FREE,
|
||||
};
|
||||
self.tasks.push(task);
|
||||
}
|
||||
|
||||
self.InitTask = function(){ // 初始化 任务,设置合约 杠杆等
|
||||
_.each(self.tasks, function(task){
|
||||
var arr = task.HedgeList.split(';');
|
||||
var hedgeDirection = 1;
|
||||
// 可扩展 恢复持仓,读取当前持仓。
|
||||
_.each(arr, function(pair){
|
||||
var tmp = pair.split(':'); // 把每个 网格节点的 单元 按照':'字符 分割成 参数 数组 tmp
|
||||
if (tmp.length != 3) { // 由于 格式 是 30:15:1 即 开仓差价: 平仓差价: 下单量 ,所以 用 ':' 分割后 tmp长度 不是3的 即 格式错误
|
||||
throw "开仓表不正确"; // 抛出异常 格式错误
|
||||
}
|
||||
var st = { // 每次迭代的时候 构造一个对象
|
||||
open: Number(tmp[0]), // 开仓 把 tmp[0] 即 30:15:1 按 ':' 分割后 生成的数组中的 第一个元素 30 , 通过 Number 函数 转换为数值
|
||||
cover: Number(tmp[1]), // 平仓..
|
||||
amount: Number(tmp[2]), // 量..
|
||||
hold: 0, // 持仓 初始为0
|
||||
ActualPrice: 0,
|
||||
PointProfit : 0, // 但个仓位累计差价。
|
||||
CoverTimes : 0, // 平仓次数
|
||||
};
|
||||
task.dic.push(st);
|
||||
});
|
||||
// 处理其它 初始化工作
|
||||
task.P = $.NewPositionManager(task.e);
|
||||
task.isUseMarketOrder = isUseMarketOrder; // 初始是否使用市价单
|
||||
task.e.SetMarginLevel(task.MarginLevel); // 设置杠杆
|
||||
task.nowAccount = _C(task.e.GetAccount); // 初始化 当前账户信息
|
||||
// 检查, 启用的网格 是否会 耗尽资金
|
||||
if((task.dic[0].open < 0 && isCreateHedgeList) || (task.dic[0].cover < 0 && isCreateHedgeList)){
|
||||
// throw "自动网格生成错误:第一个节点开仓值、平仓值 小于0,会引起产生重复部分。" +JSON.stringify(task.dic);
|
||||
}
|
||||
var dic_length = task.dic.length;
|
||||
var sumPiece = 0;
|
||||
for(var i = 0; i < dic_length; i++){
|
||||
sumPiece += task.dic[i].amount;
|
||||
}
|
||||
sumPiece = sumPiece * 2;
|
||||
task.e.SetContractType(task.symbolA);
|
||||
var tickerA = _C(task.e.GetTicker);
|
||||
task.e.SetContractType(task.symbolB);
|
||||
var tickerB = _C(task.e.GetTicker);
|
||||
var Margin = sumPiece * 100 * OK_Rate / ((tickerA.Last + tickerB.Last) / 2) / task.MarginLevel;
|
||||
if(MarginRatio * task.initAccount.Stocks < Margin){
|
||||
if(istry == false || IsVirtual()){
|
||||
throw "满仓所需保证金:" + Margin + " 超出 限制比例: " + MarginRatio;
|
||||
}else{
|
||||
Log("注意,实盘测试模式开启!#FF0000");
|
||||
}
|
||||
}
|
||||
Log("按照当前初始化,满仓将开" + sumPiece + "张合约,共需要 保证金:" + Margin + "BTC");
|
||||
});
|
||||
}
|
||||
|
||||
self.DealTask = function(nowTime){
|
||||
// 处理task 任务
|
||||
tbls = []; // 每次初始清空
|
||||
_.each(self.tasks, function(task){
|
||||
// 迭代处理 task
|
||||
task.e.SetContractType(task.symbolA);
|
||||
var Adepth = task.e.GetDepth();
|
||||
task.e.SetContractType(task.symbolB);
|
||||
var Bdepth = task.e.GetDepth();
|
||||
|
||||
if(!Adepth || !Bdepth || Adepth.Asks.length === 0 || Adepth.Bids.length === 0 || Bdepth.Asks.length === 0 || Bdepth.Bids.length === 0){
|
||||
return;
|
||||
}
|
||||
|
||||
task.Adepth = Adepth;
|
||||
task.Bdepth = Bdepth;
|
||||
|
||||
task.Adiff = _N(Adepth.Bids[0].Price - Bdepth.Asks[0].Price);
|
||||
task.Bdiff = _N(Adepth.Asks[0].Price - Bdepth.Bids[0].Price);
|
||||
|
||||
if(nowTime - task.lastUpdateLineTime > 1000 * 60){
|
||||
$.PlotLine("plus", task.Adiff);
|
||||
$.PlotLine("minus", task.Bdiff);
|
||||
task.lastUpdateLineTime = nowTime;
|
||||
}
|
||||
|
||||
// 判断解除冻结
|
||||
if(nowTime - task.FrozenStartTime > 1000 * 15 * 60 && task.isFrozen == true){
|
||||
task.isFrozen = false;
|
||||
if(For_USD == false){
|
||||
var lastRate = OK_Rate;
|
||||
OK_Rate = task.e.GetUSDCNY();
|
||||
task.e.SetRate(OK_Rate);
|
||||
}
|
||||
Log("冻结解除!", For_USD == false ? "并且更新汇率,上次汇率:" + lastRate + "更新后汇率:" + OK_Rate + "#FF0000" : "#FF0000");
|
||||
}
|
||||
|
||||
// 交易逻辑
|
||||
var SumHold = task.dic.length;
|
||||
for(var index = 0; index < task.dic.length && task.isFrozen == false; index++){
|
||||
if(task.dic[index].hold === 0){
|
||||
if(task.dic[index].open <= task.Adiff && task.State !== MINUS){ // 正对冲 空A 多B
|
||||
task.action = [index, "sell", "buy", task.dic[index].amount];
|
||||
Log(JSON.stringify(task.action));
|
||||
Hedge_Open_Cover(task);
|
||||
|
||||
$.PlotFlag(nowTime, "O", "sell-buy", "flag", "red");
|
||||
task.isLogProfit = false;
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
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];
|
||||
Log(JSON.stringify(task.action));
|
||||
Hedge_Open_Cover(task);
|
||||
|
||||
$.PlotFlag(nowTime, "O", "buy-sell", "flag", "red");
|
||||
task.isLogProfit = false;
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
task.State = MINUS;
|
||||
}else{
|
||||
SumHold--;
|
||||
}
|
||||
}else{
|
||||
if(task.dic[index].hold > 0 && task.dic[index].cover >= task.Bdiff){ // 平空A 平多B
|
||||
task.action = [index, "closesell", "closebuy", task.dic[index].hold];
|
||||
Log(JSON.stringify(task.action));
|
||||
// Buy_SymbolA_Sell_SymbolB(task);
|
||||
Hedge_Open_Cover(task);
|
||||
$.PlotFlag(nowTime, "C", "closesell-closebuy", "circlepin");
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
Log("Cover symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
}else if(task.dic[index].hold < 0 && task.dic[index].cover >= -task.Adiff){ // 平多A 平空B
|
||||
task.action = [index, "closebuy", "closesell", task.dic[index].hold];
|
||||
Log(JSON.stringify(task.action));
|
||||
// Sell_SymbolA_Buy_SymbolB(task);
|
||||
Hedge_Open_Cover(task);
|
||||
$.PlotFlag(nowTime, "C", "closebuy-closesell", "circlepin");
|
||||
task.nowAccount = _C(task.e.GetAccount);
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
Log("Cover symbolA:", task.APositions, "symbolB:", task.BPositions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(SumHold != 0 && nowTime - task.PositionsLastUpdateTime > 1000 * 30){
|
||||
var Positions = _C(task.e.GetPosition); // 获取持仓信息。
|
||||
UpdatePosition(task, Positions);
|
||||
task.PositionsLastUpdateTime = nowTime;
|
||||
}else if(SumHold == 0 && task.isLogProfit == false){
|
||||
sumProfit = 0;
|
||||
task.State = FREE;
|
||||
for(var a = 0 ; a < TC.tasks.length; a++){
|
||||
sumProfit += TC.tasks[a].taskProfit;
|
||||
}
|
||||
LogProfit(sumProfit, "当前:", task.nowAccount, "初始:", task.initAccount);
|
||||
task.taskProfit = task.nowAccount.Stocks - task.initAccount.Stocks;
|
||||
task.isLogProfit = true;
|
||||
}
|
||||
|
||||
// 检测交割剩余时间、发送 交割前平仓命令
|
||||
CheckDelivery(nowTime, "this_week", task); // 检测 当周交割。 必须在当周交割前平仓。
|
||||
|
||||
// 测试 将数据现在状态栏
|
||||
var tbl = {
|
||||
type : "table",
|
||||
title : task.symbolA + "&" + task.symbolB,
|
||||
cols : ["key", "value"],
|
||||
rows : []
|
||||
};
|
||||
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"){ // 过滤显示
|
||||
continue;
|
||||
}
|
||||
if(key === "e"){
|
||||
value = "初始: " + JSON.stringify(task.initAccount) + " 当前: " + JSON.stringify(task.nowAccount);
|
||||
key = task[key].GetName();
|
||||
}
|
||||
tbl.rows.push([key, value]);
|
||||
}
|
||||
// 判断下网格方向
|
||||
if(task.dic[0].hold < 0){
|
||||
for(var j = 0; j < task.dic.length; j++){
|
||||
var task_dic = JSON.stringify(task.dic[j]);
|
||||
if(task.dic[j].hold > 0){
|
||||
task_dic += "#FF0000";
|
||||
}else if(task.dic[j].hold < 0){
|
||||
task_dic += "#32CD32";
|
||||
}
|
||||
tbl.rows.push([j, task_dic]);
|
||||
}
|
||||
}else if(task.dic[0].hold > 0){
|
||||
for(var j = task.dic.length - 1; j >= 0; j--){
|
||||
var task_dic = JSON.stringify(task.dic[j]);
|
||||
if(task.dic[j].hold > 0){
|
||||
task_dic += "#FF0000";
|
||||
}else if(task.dic[j].hold < 0){
|
||||
task_dic += "#32CD32";
|
||||
}
|
||||
tbl.rows.push([j, task_dic]);
|
||||
}
|
||||
}else{
|
||||
for(var j = 0; j < task.dic.length; j++){
|
||||
var task_dic = JSON.stringify(task.dic[j]);
|
||||
if(task.dic[j].hold > 0){
|
||||
task_dic += "#FF0000";
|
||||
}else if(task.dic[j].hold < 0){
|
||||
task_dic += "#32CD32";
|
||||
}
|
||||
tbl.rows.push([j, task_dic]);
|
||||
}
|
||||
}
|
||||
tbls.push(tbl);
|
||||
});
|
||||
if(tbls.length === 0){ // 容错模式,或者实盘中 可能有原因导致 _.each 迭代中 返回,tbls 为 [] ,处理此种情况。
|
||||
return;
|
||||
}
|
||||
LogStatus("轮询耗时:" + StrLoopTime + " 当前时间:" + _D() + MSG_String + '\n`' + JSON.stringify(tbls) + '`'); // 输出到状态栏
|
||||
}
|
||||
|
||||
// 返回对象
|
||||
return self;
|
||||
}
|
||||
|
||||
var TC = null; // TasksController 对象
|
||||
var tbls = [];
|
||||
var MSG_String = " ";
|
||||
var StrLoopTime = "";
|
||||
var OK_Rate = 0;
|
||||
var SumUseTime = 0;
|
||||
var times = 0;
|
||||
var sumTimes = 0;
|
||||
var sumProfit = 0;
|
||||
function main(){
|
||||
// 测试代码 模拟界面参数
|
||||
if(isFilter){
|
||||
Log("启用过滤常规错误信息。");
|
||||
SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");
|
||||
}
|
||||
|
||||
var Positions = [];
|
||||
for(var j = 0 ; j < exchanges.length ; j++){
|
||||
var position = _C(exchanges[j].GetPosition);
|
||||
if(position.length !== 0){
|
||||
Positions.push(position);
|
||||
}
|
||||
}
|
||||
if(AutoRecoveryState == false && Positions.length == 0){ // 没有持仓,并且关闭了自动恢复
|
||||
if(isCreateHedgeList == true){
|
||||
HedgeTable = CreateHedgeList(begin, end, size, step, amountOfPoint, symbolA, symbolB);
|
||||
}
|
||||
|
||||
// 输出对冲控制表,并检查。
|
||||
Log("对冲控制表", HedgeTable);
|
||||
if(HedgeTable == "(this_week&quarter)30:15:1"){
|
||||
Log("注意!对冲控制表 当前为 默认值!可能引起亏损。");
|
||||
}
|
||||
|
||||
// 创建控制器对象
|
||||
TC = TasksController();
|
||||
|
||||
var exchangesNum = 0;
|
||||
var e_index = 0;
|
||||
for(var i = 0; i < exchanges.length; i++){ // 遍历交易所对象数组
|
||||
exchangesNum++;
|
||||
}
|
||||
|
||||
var arr = HedgeTable.split('(');
|
||||
|
||||
_.each(arr, function(item) {
|
||||
if (item != '') {
|
||||
var tmp = item.split(')');
|
||||
var pair = tmp[0].replace('(', '').split('&');
|
||||
// Log("pair:", pair, "tmp:", tmp); // 测试 显示 处理后的 控制表字符串
|
||||
TC.AddTask(exchanges[e_index], pair[0], pair[1], tmp[1]);
|
||||
if(For_USD){ // 设置汇率
|
||||
OK_Rate = 1;
|
||||
exchanges[e_index].SetRate(1);
|
||||
Log("使用的价格为美元计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为美元差价#FF0000"); // 币种提示
|
||||
}else{
|
||||
OK_Rate = exchanges[e_index].GetUSDCNY();
|
||||
exchanges[e_index].SetRate(OK_Rate);
|
||||
Log("使用的价格为RMB计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为RMB差价#FF0000"); // 币种提示
|
||||
}
|
||||
if(--exchangesNum < 0){
|
||||
throw "添加的交易所 和 对冲控制表 不匹配!交易所个数:" + exchanges.length + " arr:" + arr;
|
||||
}else if(exchangesNum !== 0){
|
||||
e_index++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log("交易所对象最大索引 e_index:", e_index, "关联后剩余交易所数量: exchangesNum:", exchangesNum); // 测试
|
||||
|
||||
// 调用控制器对象的初始化函数
|
||||
TC.InitTask();
|
||||
}else if(AutoRecoveryState == false && Positions.length !== 0){ // 未开启恢复,有持仓
|
||||
throw "未开启自动恢复,检测到有持仓信息:" + JSON.stringify(Positions);
|
||||
}else if(AutoRecoveryState == true && Positions.length == 0 && (istry == false || IsVirtual())){ // 开启自动恢复, 无持仓信息
|
||||
throw "未检测到持仓信息,无法恢复!";
|
||||
}else{ // 恢复持仓
|
||||
Log("恢复持仓!");
|
||||
if(isCreateHedgeList == true){
|
||||
HedgeTable = CreateHedgeList(begin, end, size, step, amountOfPoint, symbolA, symbolB);
|
||||
}
|
||||
|
||||
// 输出对冲控制表,并检查。
|
||||
Log("对冲控制表", HedgeTable);
|
||||
if(HedgeTable == "(this_week&quarter)30:15:1"){
|
||||
Log("注意!对冲控制表 当前为 默认值!可能引起亏损。");
|
||||
}
|
||||
|
||||
// 创建控制器对象
|
||||
TC = TasksController();
|
||||
|
||||
var exchangesNum = 0;
|
||||
var e_index = 0;
|
||||
for(var i = 0; i < exchanges.length; i++){ // 遍历交易所对象数组
|
||||
exchangesNum++;
|
||||
}
|
||||
|
||||
var arr = HedgeTable.split('(');
|
||||
|
||||
_.each(arr, function(item) {
|
||||
if (item != '') {
|
||||
var tmp = item.split(')');
|
||||
var pair = tmp[0].replace('(', '').split('&');
|
||||
// Log("pair:", pair, "tmp:", tmp); // 测试 显示 处理后的 控制表字符串
|
||||
TC.AddTask(exchanges[e_index], pair[0], pair[1], tmp[1]);
|
||||
if(For_USD){ // 设置汇率
|
||||
OK_Rate = 1;
|
||||
exchanges[e_index].SetRate(1);
|
||||
Log("使用的价格为美元计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为美元差价#FF0000"); // 币种提示
|
||||
}else{
|
||||
OK_Rate = exchanges[e_index].GetUSDCNY();
|
||||
exchanges[e_index].SetRate(OK_Rate);
|
||||
Log("使用的价格为RMB计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为RMB差价#FF0000"); // 币种提示
|
||||
}
|
||||
if(--exchangesNum < 0){
|
||||
throw "添加的交易所 和 对冲控制表 不匹配!交易所个数:" + exchanges.length + " arr:" + arr;
|
||||
}else if(exchangesNum !== 0){
|
||||
e_index++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Log("交易所对象最大索引 e_index:", e_index, "关联后剩余交易所数量: exchangesNum:", exchangesNum); // 测试
|
||||
|
||||
// 调用控制器对象的初始化函数
|
||||
TC.InitTask();
|
||||
var PreTC = _G("TC");
|
||||
for(var index = 0; index < TC.tasks.length ; index++){
|
||||
for(var key in TC.tasks[index]){
|
||||
if(key == "e" || key == "Adepth" || key == "Bdepth" || key == "P"){
|
||||
continue;
|
||||
}
|
||||
TC.tasks[index][key] = PreTC.tasks[index][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
var nowTime = new Date().getTime();
|
||||
TC.DealTask(nowTime);
|
||||
Sleep(Interval);
|
||||
var endTime = new Date().getTime();
|
||||
if(times < 100000){
|
||||
SumUseTime += (endTime - nowTime);
|
||||
times++;
|
||||
}else{
|
||||
SumUseTime = 0;
|
||||
times = 0;
|
||||
SumUseTime += (endTime - nowTime);
|
||||
times++;
|
||||
}
|
||||
sumTimes++;
|
||||
var avgUseTime = _N(SumUseTime / times);
|
||||
StrLoopTime = (endTime - nowTime) + " ms " + "平均耗时:" + avgUseTime + "循环次数:" + sumTimes;
|
||||
}
|
||||
}
|
||||
|
||||
function onexit(){
|
||||
Log("退出策略,自动保存状态。");
|
||||
_G("TC", TC);
|
||||
}
|
||||
/*
|
||||
1、需要是一个 期货账户 的模式。
|
||||
2、合约开仓手续费 0.03%
|
||||
3、计算手续费进开仓均价
|
||||
4、可以用市价单。
|
||||
*/
|
||||
@@ -0,0 +1,226 @@
|
||||
'''
|
||||
策略出处: https://www.botvs.com/strategy/23531
|
||||
策略名称: R-Breaker 交易策略
|
||||
策略作者: 太极
|
||||
策略描述:
|
||||
|
||||
R-Breaker 交易策略
|
||||
|
||||
'''
|
||||
|
||||
#!/usr/local/bin/python
|
||||
#-*- coding: UTF-8 -*-
|
||||
#R-Breaker 交易策略
|
||||
#策略提供者 @FJK QQ:171938416
|
||||
#改进 @太极 QQ:7650371
|
||||
|
||||
def my_buy(): #开仓
|
||||
try:
|
||||
global buy_price,buy_qty
|
||||
initAccount = ext.GetAccount() #交易模板的导出函数, 获得账户状态,保存策略运行前账户初始状态
|
||||
opAmount=1
|
||||
PositionRatio =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.',''))>=3:
|
||||
if buy_price<1:
|
||||
buy_price=_C(exchange.GetTicker).Last
|
||||
buy_qty=initAccount.Stocks
|
||||
#Log('开仓信息2 仓内还有比:',initAccount.Stocks,'进行清空','--开仓详情:',initAccount)
|
||||
return 1
|
||||
|
||||
#if int(str(initAccount.Stocks).replace('0.',''))==0:
|
||||
opAmount = _N(initAccount.Balance*PositionRatio,3) #买入数量
|
||||
Log("开仓没有币先进行 开仓买入%s元"%(str(opAmount))) #生成LOG日志
|
||||
|
||||
Dict = ext.Buy(opAmount) #买入ext.Buy
|
||||
if(Dict):#确认开仓成功
|
||||
buy_price=Dict['price'] #买入价格 #{'price': 4046.446, 'amount': 1.5}
|
||||
buy_qty=Dict['amount'] #买入数量
|
||||
#LogProfit(_N(gains,4),'开仓信息 钱:',initAccount.Balance,'--币:',initAccount.Stocks,'--开仓详情:',Dict)
|
||||
print_log(1,initAccount)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
except Exception,ex:
|
||||
Log('except Exception my_buy:',ex)
|
||||
return 0
|
||||
|
||||
|
||||
import time
|
||||
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"
|
||||
|
||||
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 #盈利
|
||||
|
||||
beng_Account = ext.GetAccount() #初始化信息
|
||||
beng_ticker = _C(exchange.GetTicker).Last#Ticker 市场行情 最后成交价
|
||||
beng_Balance=(beng_Account.Stocks*beng_ticker)+beng_Account.Balance #初始化账户钱
|
||||
def print_log(k_p,data=""): #输出
|
||||
try:
|
||||
name=""
|
||||
if k_p:
|
||||
name="开仓"
|
||||
else:
|
||||
name="平仓"
|
||||
global beng_Account,beng_ticker,beng_Balance
|
||||
global gains
|
||||
end_Account = ext.GetAccount() #当前账户信息
|
||||
end_ticker = _C(exchange.GetTicker).Last#Ticker 市场行情 最后成交价
|
||||
#################################################
|
||||
date1=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
|
||||
msg_data0=("本次开始运行时间:%s已运行:%s\r\n"%(start_time,Caltime(start_time,date1)))
|
||||
#################################################
|
||||
msg_data1=("本次初始化状态:%s\r\n当前运行状态:%s\r\n"%(beng_Account,end_Account))
|
||||
#################################################
|
||||
end_Balance=(end_Account.Stocks*end_ticker)+end_Account.Balance #当前账面上钱数
|
||||
msg_data2=("初始化钱:%s现在钱:%s盈亏:%s\r\n"%(str(beng_Balance),str(end_Balance),str(end_Balance-beng_Balance)))
|
||||
#################################################
|
||||
total = end_Account.Balance+end_Account.Stocks*_C(exchange.GetTicker).Last #账户总额
|
||||
roi = ((total/beng_Balance) -1)*100
|
||||
msg_data3=("当前状态:%s--钱:%s--币:%s--总值约:%.2f\r\n"%(str(name),str(end_Account.Balance),str(end_Account.Stocks),roi))
|
||||
#################################################
|
||||
income = total - beng_Account['Balance'] - beng_Account['Stocks']*beng_ticker #总盈亏
|
||||
msg_data4=("本次盈亏:%s(RMB)\t总盈亏:%.2f(RMB) %.2f\r\n"%(str(gains),income,roi))
|
||||
#################################################
|
||||
#盈利计算方法
|
||||
#盈利计算方法 浮动利润: 按 (现在币 - 初始币)x 现在的价格 + (现在的钱 - 初始的钱)
|
||||
diff_stocks=end_Account.Stocks-beng_Account.Stocks #比的差值
|
||||
diff_balance=end_Account.Balance-beng_Account.Balance #钱的差值
|
||||
new_end_balance=diff_stocks*end_ticker+diff_balance #实现盈亏 #当前的盈利
|
||||
#盈利计算方法 账面利润 : (现在币 x 现在价格+现在钱) - (初始币 x 初始价格 + 初始钱)
|
||||
new_end_balance2=(end_Account.Stocks*end_ticker+end_Account.Balance)-(beng_Account.Stocks*beng_ticker+beng_Account.Balance)
|
||||
msg_data5=("浮动利润:%s(RMB)\r\n账面利润:%s(RMB)\r\n"%(str(_N(new_end_balance,3)),str(_N(new_end_balance2,3))))
|
||||
#################################################
|
||||
LogStatus("初始化投入2016/9/24 投入0.2个币=等于行情800RMB\r\n",
|
||||
msg_data0,msg_data1,msg_data2,msg_data3,msg_data4,msg_data5,
|
||||
"更新时间:%s\r\n"%(date1),
|
||||
"%s"%(data)
|
||||
)
|
||||
#################################################
|
||||
#################################################
|
||||
#################################################
|
||||
except Exception,ex:
|
||||
Log('except Exception print_log:',ex)
|
||||
|
||||
def my_sell(): #平仓
|
||||
try:
|
||||
global buy_price,buy_qty,gains,ExitPeriod
|
||||
ExitPeriod = 0
|
||||
nowAccount = ext.GetAccount() #交易模板的导出函数 获取账户信息
|
||||
if nowAccount.Stocks<=0.002: #保证满足交易量
|
||||
#Log('不满足最小交易量:',nowAccount.Stocks)
|
||||
return 1
|
||||
|
||||
#history_Last=_N(Volume_averages(Ticker_list),2) #历史均价
|
||||
#cur_last = _N(_C(exchange.GetTicker).Last,2)
|
||||
|
||||
#if _N(_C(exchange.GetTicker).Last,2)>buy_price+ExitPeriod : #当前价格一定要大于 开仓价格
|
||||
if True:
|
||||
#if _N(_C(exchange.GetTicker).Last,2)>buy_price+ExitPeriod and history_Last - cur_last >0 and history_Last - cur_last < 2 : #当前价格一定要大于 开仓价格
|
||||
#Log('历史差价:',history_Last - cur_last)
|
||||
Dict = ext.Sell(nowAccount.Stocks)
|
||||
#Dict ={"price":_C(exchange.GetTicker).Last}
|
||||
if(Dict):
|
||||
#sell_count+=1
|
||||
sell_gains=(Dict['price']-buy_price)*Dict['amount']
|
||||
gains=gains+sell_gains
|
||||
buy_price=0 #买入价格
|
||||
buy_qty=0 #买入数量
|
||||
LogProfit(_N(gains,4),'平仓信息 钱:',nowAccount.Balance,'--币:',nowAccount.Stocks,'--平仓详情:',Dict)#收益曲线
|
||||
print_log(0,nowAccount)
|
||||
return 1
|
||||
else:
|
||||
current_Last = _N(_C(exchange.GetTicker).Last,2) ##当前价格
|
||||
data="不具备平仓条件:买入-当前=差价:%s-%s=%s"%(buy_price,current_Last,_N(buy_price-current_Last,2))
|
||||
print_log(0,nowAccount,data)
|
||||
return 0
|
||||
except Exception,ex:
|
||||
Log('except Exception my_sell:',ex)
|
||||
return 0
|
||||
|
||||
########################################################
|
||||
def onTick():
|
||||
try:
|
||||
records =exchange.GetRecords() #由你自己设定的周期数返回的数据
|
||||
HH = records[-2]['High'] #最日最高
|
||||
LC = records[-2]['Low'] #昨日最低
|
||||
HC = records[-2]['Close'] #昨日收盘
|
||||
LL = records[-2]['Low'] #昨日最低
|
||||
Pivot = (HH+HC+LC)/3 #枢轴点
|
||||
R1 = 2*Pivot-LC #阻力1
|
||||
R2 = Pivot+(HH-LC) #阻力2
|
||||
R3 = HH +2*(Pivot-LC) #阻力3
|
||||
|
||||
S1 = 2*Pivot-HH #支撑位1
|
||||
S2 = Pivot - (HH-LC) #支撑位2
|
||||
S3 = LC-2*(HH-Pivot) #支撑位3
|
||||
#Log('r1',R1,"R2",R2,'R3',R3)
|
||||
#Log('S1',S1,"S2",S2,'S3',S3)
|
||||
To = records[-1]['Open'] #今日开盘价
|
||||
Th = records[-1]['High'] #今日最高价
|
||||
Tl = records[-1]['Low'] #今日最低价
|
||||
current_price = _C(exchange.GetTicker).Last #当前价格
|
||||
|
||||
#当前价格>阻力3 开仓
|
||||
if current_price > R3: #突破上轨开多
|
||||
if my_buy(): #Log('多')
|
||||
return
|
||||
|
||||
#当前价格<支撑位3 平仓
|
||||
if current_price < S3: #突破下轨卖空
|
||||
if my_sell(): #Log('空')
|
||||
return
|
||||
|
||||
# 条件1 今日最高价>阻力2
|
||||
# 条件2 今日最高价<阻力3
|
||||
# 条件3 当前价格<阻力1
|
||||
# 同时具备这3个条件平仓
|
||||
if Th >R2 and Th <R3 and current_price <R1: #趋势反转卖出
|
||||
if my_sell(): #Log('空')
|
||||
return
|
||||
|
||||
# 条件1 今日最低价<支撑位2
|
||||
# 条件2 今日最低价>支撑位3
|
||||
# 条件3 当前价格<支撑位1
|
||||
# 同时具备这3个条件开仓
|
||||
if Tl <S2 and Tl >S3 and current_price <S1: #支撑位1
|
||||
if my_buy(): #Log('多')
|
||||
return
|
||||
# Log(records[-1])#今日K
|
||||
# Log(records[-2])#昨日K
|
||||
# Log(exchange.GetTicker())#当前
|
||||
|
||||
except Exception,ex:
|
||||
Log('except Exception onTick:',ex)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
global outAccount
|
||||
outAccount = ext.GetAccount() #初始化信息
|
||||
Log("run ",outAccount) #输出初始账户信息
|
||||
while True:
|
||||
onTick()
|
||||
Sleep(1000)
|
||||
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
'''
|
||||
策略出处: https://www.botvs.com/strategy/23874
|
||||
策略名称: R-Breaker11 交易策略
|
||||
策略作者: 太极
|
||||
策略描述:
|
||||
|
||||
R-Breaker 交易策略
|
||||
|
||||
'''
|
||||
|
||||
# botvs@f976b25629baf8373e73da860a54030d
|
||||
#!/usr/local/bin/python
|
||||
#-*- coding: UTF-8 -*-
|
||||
#删除反转止损
|
||||
import math
|
||||
import talib
|
||||
def adjustFloat(v):
|
||||
v =math.floor(v*1000)
|
||||
return v/1000
|
||||
|
||||
def GetAccount():
|
||||
account = _C(exchange.GetAccount)
|
||||
while account == null:
|
||||
account = _C(exchange.GetAccount)
|
||||
Sleep(1000)
|
||||
return account
|
||||
|
||||
def GetTicker():
|
||||
ticker = exchange.GetTicker()
|
||||
while ticker ==null:
|
||||
ticker = exchange.GetTicker()
|
||||
Sleep(1000)
|
||||
return ticker
|
||||
# def updateProfit(accountInit, accountNow, ticker):
|
||||
# netNow = accountNow.Balance + accountNow.FrozenBalance + ((accountNow.Stocks + accountNow.FrozenStocks) * ticker.Buy)
|
||||
# netInit = accountInit.Balance + accountInit.FrozenBalance + ((accountInit.Stocks + accountInit.FrozenStocks) * ticker.Buy)
|
||||
# LogProfit(adjustFloat(netNow - netInit), accountNow)
|
||||
|
||||
#获取当期账户总额
|
||||
def GetNowamount():
|
||||
account =GetAccount()
|
||||
ticker = exchange.GetTicker()
|
||||
return account.Balance + account.FrozenBalance + ((account.Stocks + account.FrozenStocks) * ticker.Buy)
|
||||
#获取当前账户市值
|
||||
def GetStockcap():
|
||||
account=GetAccount()
|
||||
ticker = GetTicker()
|
||||
return (account.Stocks + account.FrozenStocks) * ticker.Buy
|
||||
|
||||
|
||||
|
||||
#type 0 总持仓比例 1 可买入币的百分比
|
||||
def my_buy(ratio,type):
|
||||
try:
|
||||
global InitAccount
|
||||
account = GetAccount()
|
||||
ticker=_C(exchange.GetTicker)
|
||||
#计算买入量
|
||||
if type == 0:
|
||||
unit =(GetNowamount()/ticker.Buy)*ratio - account.Stocks - account.FrozenStocks
|
||||
else:
|
||||
unit =((GetNowamount()/ticker.Buy) - account.Stocks - account.FrozenStocks)*ratio
|
||||
|
||||
#不足最低交易退出买入操作
|
||||
if unit < exchange.GetMinStock():
|
||||
return 0
|
||||
Dict = ext.Buy(unit) #买入ext.Buy
|
||||
if(Dict):#确认开仓成功
|
||||
#buy_price=Dict['price'] #买入价格 #{'price': 4046.446, 'amount': 1.5}
|
||||
#buy_qty=Dict['amount'] #买入数量
|
||||
#LogProfit(_N(gains,4),'开仓信息 钱:',initAccount.Balance,'--币:',initAccount.Stocks,'--开仓详情:',Dict)
|
||||
#updateProfit(InitAccount, GetAccount(), GetTicker())
|
||||
Balance_log() #收益计算
|
||||
print_log(1,InitAccount)
|
||||
return 1
|
||||
return 0
|
||||
except Exception,ex:
|
||||
Log('except Exception my_buy:',ex)
|
||||
return 0
|
||||
|
||||
def my_sell(ratio,type):
|
||||
try:
|
||||
global InitAccount
|
||||
account = GetAccount()
|
||||
if type == 0:
|
||||
unit = 1
|
||||
else:
|
||||
unit =(account.Stocks + account.FrozenStocks)*ratio
|
||||
|
||||
if unit<exchange.GetMinStock():
|
||||
return 0
|
||||
|
||||
Dict = ext.Sell(unit)
|
||||
#Dict ={"price":_C(exchange.GetTicker).Last}
|
||||
if(Dict):
|
||||
#updateProfit(InitAccount, GetAccount(), GetTicker())
|
||||
Balance_log() #收益计算
|
||||
print_log(0,GetAccount())
|
||||
return 1
|
||||
except Exception,ex:
|
||||
Log('except Exception my_sell:',ex)
|
||||
return 0
|
||||
|
||||
|
||||
########################################################
|
||||
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 #盈利
|
||||
|
||||
beng_Account = ext.GetAccount() #初始化信息
|
||||
beng_ticker = _C(exchange.GetTicker).Last#Ticker 市场行情 最后成交价
|
||||
beng_Balance=(beng_Account.Stocks*beng_ticker)+beng_Account.Balance #初始化账户钱
|
||||
|
||||
def Balance_log(): #收益计算
|
||||
try:
|
||||
end_Account = ext.GetAccount() #当前账户信息
|
||||
end_ticker = _C(exchange.GetTicker).Last#Ticker 市场行情 最后成交价
|
||||
end_Balance=(end_Account.Stocks*end_ticker)+end_Account.Balance #当前账面上钱数
|
||||
LogProfit(end_Balance-beng_Balance) #记录盈利值
|
||||
except Exception,ex:
|
||||
Log('except Exception Balance_log:',ex)
|
||||
|
||||
def print_log(k_p,data=""): #输出
|
||||
try:
|
||||
name=""
|
||||
if k_p:
|
||||
name="开仓"
|
||||
else:
|
||||
name="平仓"
|
||||
global beng_Account,beng_ticker,beng_Balance
|
||||
global R1,R2,R3,S1,S2,S3
|
||||
global gains
|
||||
end_Account = ext.GetAccount() #当前账户信息
|
||||
end_ticker = _C(exchange.GetTicker).Last#Ticker 市场行情 最后成交价
|
||||
#################################################
|
||||
date1=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))
|
||||
msg_data0=("本次开始运行时间:%s已运行:%s\r\n"%(start_time,Caltime(start_time,date1)))
|
||||
#################################################
|
||||
msg_data1=("本次初始化状态:%s\r\n当前运行状态:%s\r\n"%(beng_Account,end_Account))
|
||||
#################################################
|
||||
end_Balance=(end_Account.Stocks*end_ticker)+end_Account.Balance #当前账面上钱数
|
||||
msg_data2=("初始化钱:%s现在钱:%s盈亏:%s\r\n"%(str(beng_Balance),str(end_Balance),str(end_Balance-beng_Balance)))
|
||||
#################################################
|
||||
total = end_Account.Balance+end_Account.Stocks*_C(exchange.GetTicker).Last #账户总额
|
||||
roi = ((total/beng_Balance) -1)*100
|
||||
msg_data3=("当前状态:%s--钱:%s--币:%s--总值约:%.2f\r\n"%(str(name),str(end_Account.Balance),str(end_Account.Stocks),roi))
|
||||
#################################################
|
||||
income = total - beng_Account['Balance'] - beng_Account['Stocks']*beng_ticker #总盈亏
|
||||
msg_data4=("本次盈亏:%s(RMB)\t总盈亏:%.2f(RMB) %.2f\r\n"%(str(gains),income,roi))
|
||||
#################################################
|
||||
#盈利计算方法
|
||||
#盈利计算方法 浮动利润: 按 (现在币 - 初始币)x 现在的价格 + (现在的钱 - 初始的钱)
|
||||
diff_stocks=end_Account.Stocks-beng_Account.Stocks #比的差值
|
||||
diff_balance=end_Account.Balance-beng_Account.Balance #钱的差值
|
||||
new_end_balance=diff_stocks*end_ticker+diff_balance #实现盈亏 #当前的盈利
|
||||
#盈利计算方法 账面利润 : (现在币 x 现在价格+现在钱) - (初始币 x 初始价格 + 初始钱)
|
||||
new_end_balance2=(end_Account.Stocks*end_ticker+end_Account.Balance)-(beng_Account.Stocks*beng_ticker+beng_Account.Balance)
|
||||
msg_data5=("浮动利润:%s(RMB)\r\n账面利润:%s(RMB)\r\n"%(str(_N(new_end_balance,3)),str(_N(new_end_balance2,3))))
|
||||
msg_data6 ='R1',R1,'R2',R2,'R3',R3,'\r\n'
|
||||
msg_data7 ='S1',S1,'S2',S2,'S3',S3,'\r\n'
|
||||
msg_data8 ="当前价格:",end_ticker,'\r\n'
|
||||
#################################################
|
||||
LogStatus("初始化投入2016/9/24 投入0.2个币=等于行情800RMB\r\n",
|
||||
msg_data0,msg_data1,msg_data2,msg_data3,msg_data4,msg_data5,msg_data6,msg_data7,msg_data8,
|
||||
"更新时间:%s\r\n"%(date1),
|
||||
"%s"%(data)
|
||||
)
|
||||
#################################################
|
||||
#################################################
|
||||
#################################################
|
||||
except Exception,ex:
|
||||
Log('except Exception print_log:',ex)
|
||||
|
||||
|
||||
|
||||
|
||||
def _GetCommand():
|
||||
get_command=GetCommand()
|
||||
if get_command:
|
||||
global K1,K2,N
|
||||
arr =get_command.split(":")
|
||||
if arr[0] == 'K1':
|
||||
K1 = float(arr[-1])
|
||||
if arr[0] =='K2':
|
||||
K2 = float(arr[-1])
|
||||
if arr[0] =='N':
|
||||
N = int(arr[-1])
|
||||
|
||||
|
||||
N=2
|
||||
|
||||
LastDeal = 0 #上次交易时间
|
||||
def onTick(exchange):
|
||||
try:
|
||||
global R1,R2,R3,S1,S2,S3,short_state_buy,short_state_sell,LastDeal,task_state,buy_count,sell_count
|
||||
amount = GetAccount() # 获取账户状态
|
||||
records =exchange.GetRecords() #默认5分钟
|
||||
To = records[-1]['Open'] #今日开盘价
|
||||
Th = records[-1]['High'] #今日最高价
|
||||
Tl = records[-1]['Low'] #今日最低
|
||||
time = records[-1].Time
|
||||
if LastDeal == time:
|
||||
return 0
|
||||
else:
|
||||
LastDeal = 0
|
||||
|
||||
|
||||
records1 =exchange.GetRecords(PERIOD_M30) #监控周期
|
||||
#time =(records1[-2].Time - records1[-1].Time)/(60*1000)
|
||||
#Log(time);
|
||||
records.pop()
|
||||
records1.pop()
|
||||
ma5 = TA.MA(records1,5)
|
||||
ma10 = TA.MA(records1,10)
|
||||
|
||||
|
||||
|
||||
# HH = records[-2]['High'] #最日最高
|
||||
# LC = records[-2]['Low'] #昨日最低
|
||||
HC = records[-1]['Close'] #昨日收盘
|
||||
# LL = records[-2]['Low'] #昨日最低
|
||||
HH = TA.Highest(records,N,'High') #N日high的最高价
|
||||
#lc = records[-2]['Low']
|
||||
#HC = TA.Lowest(records,N,'Close') #//N日close的最低价
|
||||
#hc = records[-2]['Close']
|
||||
#HH = TA.Highest(records,N,'Close') #N日close的最高价
|
||||
#ll = records[-2]['Low']
|
||||
LC = TA.Lowest(records,N,'Low') #//N日low的最低价
|
||||
#HC = TA.Highest(records,N,'Close')
|
||||
if ma5[-1] <ma10[-1]:
|
||||
HC = records[-1]['Open']
|
||||
|
||||
Pivot = (HH+HC+LC)/3 #枢轴点
|
||||
Pivot = Pivot
|
||||
R1 = 2*Pivot-LC #阻力1W
|
||||
R2 = Pivot+(HH-LC) #阻力2
|
||||
R3 = HH +2*(Pivot-LC) #阻力3
|
||||
|
||||
S1 = 2*Pivot-HH
|
||||
S2 = Pivot - (HH-LC)
|
||||
S3 = LC-2*(HH-Pivot)
|
||||
# Log('r1',R1,"R2",R2,'R3',R3)
|
||||
# Log('S1',S1,"S2",S2,'S3',S3)
|
||||
|
||||
current_price = _C(exchange.GetTicker).Last #当前价格
|
||||
capratio = (amount.Stocks + amount.FrozenStocks)/GetNowamount()
|
||||
#突破上轨 和半小时 均线向上 资金大于100 则买入
|
||||
if ma5[-1] >ma10[-1] :
|
||||
if current_price > R3 and amount.Balance > 100 and ma5[-1] >ma10[-1] and capratio <0.8 and buy_count <3 :
|
||||
# Log(ma5[-1],ma10[-1])
|
||||
Log('开多')
|
||||
if my_buy(0.4,1):
|
||||
LastDeal = time
|
||||
sell_count = 0
|
||||
buy_count+=1
|
||||
return
|
||||
#突破下轨卖空 有币 进入卖出操作
|
||||
if current_price < S3 and amount.Stocks > 0.03 :
|
||||
Log('清仓')
|
||||
if my_sell(1,0):
|
||||
sell_count+=1
|
||||
buy_count = 0
|
||||
LastDeal = time
|
||||
return
|
||||
if Th >R2 and Th <R3 and current_price <R1 and current_price >S1 and amount.Stocks > 0.003 and buy_count <3:
|
||||
Log('趋势反转卖')
|
||||
if my_sell(0.5,1):
|
||||
LastDeal = time
|
||||
buy_count = 0
|
||||
sell_count+=1
|
||||
return
|
||||
if Tl <S2 and Tl >S3 and current_price <S1 and current_price < R1 and capratio <0.6 and ma5[-1] >ma10[-1] and buy_count <3 :
|
||||
#Log(ma5[-1],ma10[-1])
|
||||
Log('趋势反转买')
|
||||
if my_buy(0.2,1):
|
||||
buy_count+=1
|
||||
sell_count = 0
|
||||
LastDeal = time
|
||||
return
|
||||
else :
|
||||
if(current_price > R3 and amount.Stocks > 0.03):
|
||||
if my_sell(0.5,1):
|
||||
Log('测试买')
|
||||
LastDeal = time
|
||||
return
|
||||
|
||||
if (current_price < S3 and ma5[-1] >ma5[-5]):
|
||||
if my_buy(0.05,1):
|
||||
Log('测试买入')
|
||||
LastDeal = time
|
||||
buy_count = 0
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
except Exception,ex:
|
||||
Log('except Exception onTick:',ex)
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
global outAccount,init_price,InitAccount,short_state_buy,short_state_sell,task_state,buy_count,sell_count
|
||||
init_price = _C(exchange.GetTicker).Last
|
||||
InitAccount = GetAccount()
|
||||
Log(init_price)
|
||||
short_state_buy =short_state_sell = 0
|
||||
task_state =0
|
||||
buy_count = 0
|
||||
sell_count = 0
|
||||
while True:
|
||||
onTick(exchange)
|
||||
nowAccount = ext.GetAccount() #交易模板的导出函数 获取账户信息
|
||||
print_log(0,nowAccount)
|
||||
Sleep(1000)
|
||||
@@ -4,7 +4,11 @@
|
||||
> 开源策略列表
|
||||
|
||||
|
||||
- [Jason](https://www.botvs.com/strategy/36875)
|
||||
- [OKCoin期货跨期对冲策略](https://www.botvs.com/strategy/34878)
|
||||
- [实盘账户模拟器](https://www.botvs.com/strategy/35977)
|
||||
- [移植 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)
|
||||
@@ -27,7 +31,7 @@
|
||||
- [全球10大交易系统之 Aberration 多品种商品期货交易系统](https://www.botvs.com/strategy/25943)
|
||||
- [获取和讯期货数据(Python版本)](https://www.botvs.com/strategy/26017)
|
||||
- [高频收割机一号](https://www.botvs.com/strategy/6237)
|
||||
- [高精度回测](https://www.botvs.com/strategy/11575)
|
||||
- [R-Breaker 交易策略](https://www.botvs.com/strategy/23531)
|
||||
- [多平台对冲稳定套利 V2.1 (复制)](https://www.botvs.com/strategy/23718)
|
||||
- [(13)策略框架](https://www.botvs.com/strategy/20663)
|
||||
- [python版现货数字货币交易类库](https://www.botvs.com/strategy/21104)
|
||||
|
||||
+363
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/35977
|
||||
策略名称: 实盘账户模拟器
|
||||
策略作者: 小小梦
|
||||
策略描述:
|
||||
|
||||
实盘 账户模拟器
|
||||
用于在实盘环境中,模拟交易,不真实下单。
|
||||
减少测试成本。
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
------------------- ------------------------ -------
|
||||
VirtualExchangeList 0, 3, 10000; 1, 4, 15000 模拟交易所列表
|
||||
isUse true 是否启用
|
||||
*/
|
||||
|
||||
/*参数
|
||||
*/
|
||||
|
||||
//功能函数
|
||||
var VirtualIndex = 0;
|
||||
var Originals = [];
|
||||
var Accounts = [];
|
||||
var VirtualOrderID = 0;
|
||||
var VirtualOrders = [];
|
||||
var BUY = 0;
|
||||
var SELL = 1;
|
||||
|
||||
// 功能函数
|
||||
function CalcMarketOrderDealPrice(Amount, current_e_Index, direction){
|
||||
var depth = null;
|
||||
var dealPrice = null;
|
||||
while(true){
|
||||
depth = exchanges[current_e_Index].GetDepth();
|
||||
if(depth && depth.Asks.length !== 0 && depth.Bids.length !== 0){
|
||||
break;
|
||||
}
|
||||
Sleep(500);
|
||||
}
|
||||
var deep = null;
|
||||
var sumAmount = 0;
|
||||
var sumPay = 0;
|
||||
direction == BUY ? deep = depth.Asks : deep = depth.Bids;
|
||||
for(var i = 0 ; i < deep.length ; i++){
|
||||
sumAmount += deep[i].Amount;
|
||||
if(Amount < sumAmount){
|
||||
sumPay += (Amount - (sumAmount - deep[i].Amount));
|
||||
dealPrice = _N(sumPay / Amount);
|
||||
}
|
||||
sumPay += deep[i].Amount * deep[i].Price;
|
||||
}
|
||||
return dealPrice;
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
function init(){
|
||||
if(isUse){
|
||||
var maxlenth = exchanges.length;
|
||||
var VE_str = VirtualExchangeList.split(';');
|
||||
var VES = [];
|
||||
if(maxlenth < VE_str.length){
|
||||
throw "VirtualExchangeList 参数 与 添加的交易所 不匹配!--> VirtualExchangeList:" + VirtualExchangeList;
|
||||
}
|
||||
|
||||
for(var i = 0 ; i < VE_str.length; i++){
|
||||
var ele_array = VE_str[i].split(',');
|
||||
|
||||
if(ele_array.length !== 3 || isNaN(Number(ele_array[0])) || isNaN(Number(ele_array[1])) || isNaN(Number(ele_array[2]))){
|
||||
throw "VirtualExchangeList 参数错误: " + ele_array;
|
||||
}
|
||||
var VE = {
|
||||
exchangeIndex : Number(ele_array[0]),
|
||||
VirtualStocks : Number(ele_array[1]),
|
||||
VirtualBalance : Number(ele_array[2]),
|
||||
};
|
||||
VES.push(VE);
|
||||
}
|
||||
for(var x = 0 ; x < VES.length ; x++){
|
||||
$.OpenVirtual(exchanges[VES[x].exchangeIndex], VES[x].VirtualStocks, VES[x].VirtualBalance);
|
||||
Log("初始化交易所模拟账户,名称:", exchanges[VES[x].exchangeIndex].GetName(), "模拟账户信息:", _C(exchanges[VES[x].exchangeIndex].GetAccount), "手续费:",exchanges[VES[x].exchangeIndex].GetFee());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出函数
|
||||
$.OpenVirtual = function(e, Stocks, Balance){
|
||||
var obj = {};
|
||||
if(typeof(e) !== "object"){
|
||||
throw "需要模拟的交易所对象错误,e参数类型:" + typeof(e);
|
||||
}
|
||||
if(e.GetName() === 'undefined'){
|
||||
throw "参数e 不是交易所对象:";
|
||||
}
|
||||
|
||||
VirtualIndex++;
|
||||
e.VirtualIndex = VirtualIndex;
|
||||
|
||||
var Original = {
|
||||
IndexOn_exchanges : null,
|
||||
Name : null,
|
||||
GetAccount : null,
|
||||
Buy : null,
|
||||
Sell : null,
|
||||
GetOrder : null,
|
||||
Go : null,
|
||||
Fee : null,
|
||||
};
|
||||
|
||||
var current_e_Index = null;
|
||||
for(var i = 0; i < exchanges.length; i++){
|
||||
if(exchanges[i].VirtualIndex === VirtualIndex){
|
||||
current_e_Index = i;
|
||||
}
|
||||
}
|
||||
|
||||
// 储存原始 引用, 其它数据
|
||||
Original.IndexOn_exchanges = current_e_Index;
|
||||
Original.GetAccount = e.GetAccount;
|
||||
Original.Buy = e.Buy;
|
||||
Original.Sell = e.Sell;
|
||||
Original.GetOrder = e.GetOrder;
|
||||
Original.Go = e.Go;
|
||||
Original.Name = e.GetName();
|
||||
Original.Fee = e.GetFee();
|
||||
|
||||
var Account = {
|
||||
Stocks: Stocks, // Stocks
|
||||
FrozenStocks : 0, // FrozenStocks
|
||||
Balance : Balance, // Balance
|
||||
FrozenBalance : 0 // FrozenBalance
|
||||
};
|
||||
|
||||
Accounts[current_e_Index] = Account;
|
||||
Originals[current_e_Index] = Original;
|
||||
|
||||
// 替换API
|
||||
exchanges[current_e_Index].GetAccount = function(){
|
||||
// 需要深拷贝
|
||||
return cloneObj(Accounts[current_e_Index]); // clone
|
||||
}
|
||||
|
||||
exchanges[current_e_Index].Buy = function(Price, Amount){
|
||||
// 处理默认参数
|
||||
var args = arguments;
|
||||
var parm = "";
|
||||
if(args && args.length > 2){
|
||||
for(var j = 2 ; j < args.length; j++){
|
||||
parm += args[j];
|
||||
}
|
||||
}
|
||||
|
||||
if(Price == -1){ // 处理市价单
|
||||
// 输出Log
|
||||
Log(Originals[current_e_Index].Name, " 买入 " + "市价单" + " " + Amount + " " + parm + "#007FFF"); // blue
|
||||
var dealPrice = CalcMarketOrderDealPrice(Amount, current_e_Index, BUY); // 根据市价单下单量计算盘口 可吃单的实际成交价。
|
||||
|
||||
|
||||
if(dealPrice * Amount > Accounts[current_e_Index].Balance){
|
||||
Log("错误:没有足够的钱买:", "数量:", Amount, Accounts[current_e_Index]);
|
||||
return;
|
||||
}
|
||||
// 更新账户数据
|
||||
Accounts[current_e_Index].Stocks += (Amount - Originals[current_e_Index].Fee.Buy * Amount); // 扣除手续费
|
||||
Accounts[current_e_Index].Balance -= Amount * dealPrice;
|
||||
|
||||
// 返回ID
|
||||
if(VirtualOrderID > Number.MAX_VALUE - 100){
|
||||
VirtualOrderID = 0;
|
||||
}
|
||||
VirtualOrderID++;
|
||||
|
||||
// 模拟产生order
|
||||
var order = {"Id": VirtualOrderID, "Price": Price, "Amount": Amount, "DealAmount": Amount, "Type": 0, "Status": 1, "AvgPrice": dealPrice};
|
||||
VirtualOrders.push(order);
|
||||
|
||||
return VirtualOrderID;
|
||||
}else{ // 限价单处理的有问题
|
||||
// 输出Log
|
||||
Log(Originals[current_e_Index].Name, " 买入 " + Price + " " + Amount + " " + parm + "#007FFF"); // blue
|
||||
|
||||
var ticker = _C(exchanges[current_e_Index].GetTicker);
|
||||
if(Price > ticker.Last + 10 || Price < ticker.Last - 10){
|
||||
Log("错误:下单价格无效,当前最后成交价:", ticker.Last, "ticker:", ticker);
|
||||
return;
|
||||
}
|
||||
if(Price * Amount > Accounts[current_e_Index].Balance){
|
||||
Log("错误:下单价格无效,没有足够的钱买, Price:", Price, "数量:", Amount);
|
||||
return;
|
||||
}
|
||||
// 更新账户数据
|
||||
Accounts[current_e_Index].Stocks += Amount;
|
||||
Accounts[current_e_Index].Balance -= Amount * Price;
|
||||
|
||||
// 返回ID
|
||||
if(VirtualOrderID > Number.MAX_VALUE - 100){
|
||||
VirtualOrderID = 0;
|
||||
}
|
||||
VirtualOrderID++;
|
||||
|
||||
// 模拟产生order
|
||||
var order = {"Id": VirtualOrderID, "Price": Price, "Amount": Amount, "DealAmount": Amount, "Type": 0, "Status": 1, "AvgPrice": Price};
|
||||
VirtualOrders.push(order);
|
||||
|
||||
return VirtualOrderID;
|
||||
}
|
||||
}
|
||||
|
||||
exchanges[current_e_Index].Sell = function(Price, Amount){
|
||||
//Log("测试Sell"); // 测试
|
||||
// 处理默认参数
|
||||
var args = arguments;
|
||||
var parm = "";
|
||||
if(args && args.length > 2){
|
||||
for(var j = 2 ; j < args.length; j++){
|
||||
parm += args[j];
|
||||
}
|
||||
}
|
||||
|
||||
if(Price == -1){ // 处理市价单
|
||||
// 输出Log
|
||||
Log(Originals[current_e_Index].Name, " 卖出 " + "市价单" + " " + Amount + " " + parm + "#32CD32"); // green
|
||||
var dealPrice = CalcMarketOrderDealPrice(Amount, current_e_Index, SELL); // 根据市价单下单量计算盘口 可吃单的实际成交价。
|
||||
|
||||
if(Amount > Accounts[current_e_Index].Stocks){
|
||||
Log("错误:没有足够的 标的物:", "数量:", Amount, Accounts[current_e_Index]);
|
||||
return;
|
||||
}
|
||||
// 更新账户数据
|
||||
Accounts[current_e_Index].Stocks -= Amount;
|
||||
Accounts[current_e_Index].Balance += (Amount * dealPrice - Originals[current_e_Index].Fee.Sell * Amount * dealPrice); // 扣除手续费
|
||||
|
||||
// 返回ID
|
||||
if(VirtualOrderID > Number.MAX_VALUE - 100){
|
||||
VirtualOrderID = 0;
|
||||
}
|
||||
VirtualOrderID++;
|
||||
|
||||
// 模拟产生order
|
||||
var order = {"Id": VirtualOrderID, "Price": Price, "Amount": Amount, "DealAmount": Amount, "Type": 1, "Status": 1, "AvgPrice": dealPrice};
|
||||
VirtualOrders.push(order);
|
||||
|
||||
return VirtualOrderID;
|
||||
}else{ // 限价单处理的有问题
|
||||
// 输出Log
|
||||
Log(Originals[current_e_Index].Name, " 卖出 " + Price + " " + Amount + " " + parm + "#32CD32"); // green
|
||||
|
||||
var ticker = _C(exchanges[current_e_Index].GetTicker);
|
||||
if(Price > ticker.Last + 10 || Price < ticker.Last - 10){
|
||||
Log("错误:下单价格无效,当前最后成交价:", ticker.Last, "ticker:", ticker);
|
||||
return;
|
||||
}
|
||||
if(Amount > Accounts[current_e_Index].Stocks){
|
||||
Log("错误:下单价格无效,没有足够的 标的物, Price:", Price, "数量:", Amount);
|
||||
return;
|
||||
}
|
||||
// 更新账户数据
|
||||
Accounts[current_e_Index].Stocks -= Amount;
|
||||
Accounts[current_e_Index].Balance += Amount * Price;
|
||||
|
||||
// 返回ID
|
||||
if(VirtualOrderID > Number.MAX_VALUE - 100){
|
||||
VirtualOrderID = 0;
|
||||
}
|
||||
VirtualOrderID++;
|
||||
|
||||
// 模拟产生order
|
||||
var order = {"Id": VirtualOrderID, "Price": Price, "Amount": Amount, "DealAmount": Amount, "Type": 1, "Status": 1, "AvgPrice": Price};
|
||||
VirtualOrders.push(order);
|
||||
|
||||
return VirtualOrderID;
|
||||
}
|
||||
}
|
||||
|
||||
exchanges[current_e_Index].GetOrder = function(OrderId){
|
||||
if(VirtualOrders.length > 300){
|
||||
VirtualOrders.shift();
|
||||
}
|
||||
for(var i = 0 ; i < VirtualOrders.length ; i++){
|
||||
if(OrderId == VirtualOrders[i].Id){
|
||||
return VirtualOrders[i];
|
||||
}
|
||||
}
|
||||
Log("错误:查询无此ID订单", OrderId);
|
||||
return null;
|
||||
}
|
||||
|
||||
exchanges[current_e_Index].Go = function(arg1){
|
||||
var args = arguments;
|
||||
if(arg1 == "Buy" || arg1 == "Sell" || arg1 == "GetAccount" || arg1 == "GetOrder"){
|
||||
var GoObj = {};
|
||||
if(arg1 == "Buy"){
|
||||
GoObj.wait = function(time){
|
||||
return exchanges[current_e_Index].Buy(args[1], args[2]);
|
||||
}
|
||||
return GoObj;
|
||||
}else if(arg1 == "Sell"){
|
||||
GoObj.wait = function(time){
|
||||
return exchanges[current_e_Index].Sell(args[1], args[2]);
|
||||
}
|
||||
return GoObj;
|
||||
}else if(arg1 == "GetAccount"){
|
||||
GoObj.wait = function(time){
|
||||
return exchanges[current_e_Index].GetAccount();
|
||||
}
|
||||
return GoObj;
|
||||
}else if(arg1 == "GetOrder"){
|
||||
GoObj.wait = function(time){
|
||||
return exchanges[current_e_Index].GetOrder(args[1]);
|
||||
}
|
||||
return GoObj;
|
||||
}
|
||||
}else{
|
||||
// exchanges[current_e_Index].Go = Originals[current_e_Index].Go;
|
||||
// Log(current_e_Index, Originals[current_e_Index].Go, arg1, args); // ceshi
|
||||
if(args.length === 3){
|
||||
return Originals[current_e_Index].Go(arg1, args[1], args[2]);
|
||||
}else if(args.length === 2){
|
||||
return Originals[current_e_Index].Go(arg1, args[1]);
|
||||
}else if(args.length === 1){
|
||||
return Originals[current_e_Index].Go(arg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
$.CloseVirtual = function(e){
|
||||
|
||||
};
|
||||
|
||||
$.SetSloid = function(){
|
||||
|
||||
};
|
||||
|
||||
// 测试
|
||||
function main(){
|
||||
Log(exchange.GetAccount())
|
||||
Log(exchange.Go("GetDepth").wait())
|
||||
$.OpenVirtual(exchange, 20, 300);
|
||||
var initAccount = exchange.GetAccount();
|
||||
Log(initAccount);
|
||||
Log(exchange.Go("GetDepth").wait())
|
||||
}
|
||||
|
||||
/*
|
||||
1、order 的结构 {"Id": 3, "Price": 1111, "Amount": 12, "DealAmount": 12, "Type": 1, "Status": 1, "AvgPrice": 0} // 0 Buy 1 Sell
|
||||
*/
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
策略出处: https://www.botvs.com/strategy/11575
|
||||
策略名称: 高精度回测
|
||||
策略作者: 数·狂
|
||||
策略描述:
|
||||
|
||||
由于当前回测系统对K线周期的支持不够完善,在回测系统中无法使用自定义周期,且使用长周期进行回测时数据点不够密集。采用此方法可以增加回测的数据点密度,获得更准确的结果,只需在回测时使用,实盘时无需使用本模板。
|
||||
|
||||
使用方法:
|
||||
exchange.GetRecords() ==> $.GetRecords(exchange, period)
|
||||
其中period的单位为分钟。
|
||||
回测K线周期应该尽可能选小(例如:回测近1个月内选1分钟,近5个月内选5分钟,等等),且period应是回测周期的倍数。
|
||||
|
||||
|
||||
参数 默认值 描述
|
||||
---- ----- ----------
|
||||
tz 8 时区 (UTC+X)
|
||||
*/
|
||||
|
||||
$.GetRecords = function (exchange, period) {
|
||||
var prevT;
|
||||
var rec1 = exchange.GetRecords();
|
||||
if (!rec1) return null;
|
||||
var recN = [];
|
||||
var tmp = {Time: null, Open: null, High: null, Low: null, Close: null, Volume: 0};
|
||||
for (var i = 0; i < rec1.length; i++) {
|
||||
if (!prevT || Math.floor((rec1[i].Time+tz*3600000) / (period*60000)) > prevT) {
|
||||
prevT = Math.floor((rec1[i].Time+tz*3600000) / (period*60000));
|
||||
tmp.Time = rec1[i].Time;
|
||||
tmp.Open = rec1[i].Open;
|
||||
tmp.High = rec1[i].High;
|
||||
tmp.Low = rec1[i].Low;
|
||||
tmp.Close = rec1[i].Close;
|
||||
tmp.Volume = rec1[i].Volume;
|
||||
}
|
||||
else if (tmp.Time){
|
||||
tmp.High = Math.max(tmp.High, rec1[i].High);
|
||||
tmp.Low = Math.min(tmp.Low, rec1[i].Low);
|
||||
tmp.Close = rec1[i].Close;
|
||||
tmp.Volume += rec1[i].Volume;
|
||||
}
|
||||
if ((i == rec1.length-1 || Math.floor((rec1[i+1].Time+tz*3600000) / (period*60000)) > prevT) && tmp.Time) {
|
||||
recN.push({Time: tmp.Time, Open: tmp.Open, High: tmp.High, Low: tmp.Low, Close: tmp.Close, Volume: tmp.Volume});
|
||||
}
|
||||
}
|
||||
return recN;
|
||||
};
|
||||
|
||||
function main() {
|
||||
Log($.GetRecords(exchange,20*1440)); // 20日K线
|
||||
Log(new Date($.GetRecords(exchange,1440)[0].Time).toString()); //测试日K线时间戳
|
||||
Log(new Date($.GetRecords(exchange,1440)[1].Time).toString());
|
||||
Log(new Date($.GetRecords(exchange,1440)[2].Time).toString());
|
||||
}
|
||||
Reference in New Issue
Block a user