This commit is contained in:
botvs
2017-02-27 09:22:50 +08:00
parent 82b672e719
commit c3019f6709
7 changed files with 1926 additions and 55 deletions
+83
View File
@@ -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)
}
}
+913
View File
@@ -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、可以用市价单。
*/
+226
View File
@@ -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)
+336
View File
@@ -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)
+5 -1
View File
@@ -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
View File
@@ -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
*/
-54
View File
@@ -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());
}