Name
常用函数扩展增强类库-Ver-003
Author
ChaoZhang
Source (javascript)
/*
* @Project: 官方扩展增强类库
* @Version: Ver 0.0.3
* @Author: RedSword <[email protected]>
* @Description:收集整理常用增强函数
* @Date: 2021-05-06 11:02:29
* @LastEditors: RedSword
* @LastEditTime: 2021-09-07 11:35:52
* @Copyright:: Copyright © 2020 FMZ Quant
* 代码规范参考: https://github.com/fex-team/styleguide/blob/master/javascript.md
*/
/* jshint esversion: 6 */
/**
* @Title: 转北京时间
* @description: 将托管者所在服务器时间转为北京时间
* @param {time} localtime 所在时间
* @return {time} 北京时间
* @example
* var localDate = $.ToBJTime(new Date());
* Log(localDate) //Thu May 06 2021 11:19:45 GMT+0000
* Log(localDate.getTime()) //1620299985696
*/
$.ToBJTime = function (localDate) {
return new Date(localDate.getTime() + localDate.getTimezoneOffset() * 60000 + 3600000 * 8);
};
/**
* 将日期格式化成指定格式的字符串
* @param date 要格式化的日期,不传时默认当前时间,也可以是一个时间戳
* @param fmt 目标字符串格式,支持的字符有:y,M,d,q,w,H,h,m,S,默认:yyyy-MM-dd HH:mm:ss
* @returns 返回格式化后的日期字符串
*/
$.FormatDate = function (date, fmt) {
date = !date ? new Date() : date;
date = typeof date === "number" ? new Date(date) : date;
fmt = fmt || "yyyy-MM-dd HH:mm:ss";
var obj = {
y: date.getFullYear(), // 年份,注意必须用getFullYear
M: date.getMonth() + 1, // 月份,注意是从0-11
d: date.getDate(), // 日期
q: Math.floor((date.getMonth() + 3) / 3), // 季度
w: date.getDay(), // 星期,注意是0-6
H: date.getHours(), // 24小时制
h: date.getHours() % 12 == 0 ? 12 : date.getHours() % 12, // 12小时制
m: date.getMinutes(), // 分钟
s: date.getSeconds(), // 秒
S: date.getMilliseconds(), // 毫秒
};
var week = ["天", "一", "二", "三", "四", "五", "六"];
for (var i in obj) {
fmt = fmt.replace(new RegExp(i + "+", "g"), function (m) {
var val = obj[i] + "";
if (i == "w") return (m.length > 2 ? "星期" : "周") + week[val];
for (var j = 0, len = val.length; j < m.length - len; j++) val = "0" + val;
return m.length == 1 ? val : val.substring(val.length - m.length);
});
}
return fmt;
};
/**
* @Title: 获取永久缓存
* @description:当缓存不存在时,写入缓存,如果存在就返回数据,一般记录初始价格使用
* @param {string} key 唯一标示
* @param {*} data 要保存的数据
* @return {*}
*
*/
$.ForeverCache = function (key, data) {
key = "ForeverCache" + key;
var getDate = _G(key);
if (getDate == null) {
_G(key, data);
return data;
}
return getDate;
};
/**
* @title: 当天缓存
* @description:获取当天的缓存,每天北京时间0点0分重置数据
* @param {string} key 唯一标示
* @param {*} data 要保存的数据
* @return {*}
*/
$.TodayCache = function (key, data) {
key = "TodayCache" + key;
var today = $.ToBJTime(new Date()).getDate();
if (_G("TodayCacheToday_" + key) !== today) {
_G("TodayCacheToday_" + key, today);
_G(key, data);
return data;
} else {
return _G(key);
}
};
/**
* @title: 定时执行函数
* @description: 指定时间间隔,来执行函数
* @param {int} second 间隔时间,为秒
* @param {string} key 标识
* @param {function} fun 要执行的函数
* @return {*} 定时执行函数的结果
* @example
* //每60秒执行一次nowTime()函数
* Log($.ExecuteFuncForTime(60,"myTime",nowTime))
*/
$.ExecuteFuncForTime = function (second, key, fun) {
var endSecond = second * 1000;
var nowTime = new Date().getTime();
if (_G("funcForTime_" + key) == null || nowTime - _G("funcForTime_" + key) > endSecond) {
var data = fun();
_G("funcForTime_" + key, nowTime);
_G(key, data);
return data;
} else {
return _G(key);
}
};
/**
* @title: Object排序
* @description:根据指定的标识符,对Object进行排序
* @param {object} obj 要排序的对象
* @param {string} key 标识符
* @return {object}
* @example
* var obj = { aa: { f: 2 }, bb: { f: 1 }, cc: { f: 3 } };
* Log(sortobjkey(obj,'f')) //{"cc":{"f":3},"aa":{"f":2},"bb":{"f":1}}
*/
$.SortObjectKey = function (obj, key) {
var o = {};
Object.keys(obj)
.map(function (k, i) {
return [k, obj[k]];
})
.sort(function (a, b) {
k = key;
if (a[1][k] > b[1][k]) return -1;
if (a[1][k] < b[1][k]) return 1;
return 0;
})
.forEach(function (a) {
o[a[0]] = a[1];
});
return o;
};
/**
* @title:策略运行时间
* @description:记录第一次运行时间并计算已经运行的时间数
* @return {object} 对象
* @example
* Log($.RunTime())
* //{"RunSeconds":18170,"NowUnix":1622821609901,"NowTime":"2021-06-04 23:46:49","FormatTime":"运行时间: 0 天 5 时 2 分 50 秒","StartTime":"2021-06-04 18:43:59"}
*/
$.RunTime = function () {
var startTime = new Date($.ForeverCache("startTime", new Date()));
var between = $.TimeBetween(startTime, new Date());
var timestamp = parseInt(UnixNano() / 1000000);
let week = $.GetWeek($.ToBJTime(new Date()));
return {
RunSeconds: parseInt((timestamp - startTime.getTime()) / 1000), //运行秒数
NowUnix: timestamp, //当间时间戳
NowTime: _D($.ToBJTime(new Date())), //当前时间
NowYear: week.year,
NowMonth: week.month,
NowDay: week.day,
NowWeek: week.week,
FormatTime: "运行时间: " + between.days + " 天 " + between.hours + " 时 " + between.minutes + " 分 " + between.seconds + " 秒", //格式化后的运行时间
StartTime: _D($.ToBJTime(startTime)), //开始时间
StartUnix: $.ForeverCache("StartUnix", timestamp),
};
};
$.TimeBetween = function (startDate, endDate) {
let delta = Math.abs(endDate - startDate) / 1000;
const isNegative = startDate > endDate ? -1 : 1;
return [
["days", 24 * 60 * 60],
["hours", 60 * 60],
["minutes", 60],
["seconds", 1],
].reduce((acc, [key, value]) => ((acc[key] = Math.floor(delta / value) * isNegative), (delta -= acc[key] * isNegative * value), acc), {});
};
$.GetAnalyze = function (totalAssets) {
var sqlDB;
try {
sqlDB = DBExec("select * from profit");
} catch (error) {
return false;
}
var profits = sqlDB.values;
if (profits.length == 0) {
return {
totalAssets: totalAssets,
yearDays: 0,
totalReturns: 0,
annualizedReturns: 0,
sharpeRatio: 0,
volatility: 0,
nowDrawdown: 0,
maxDrawdown: 0,
maxDrawdownTime: 0,
maxAssetsTime: 0,
maxDrawdownStartTime: 0,
winningRate: 0,
nowDrawdownFormat: {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
},
maxDrawdownFormat: {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
},
};
}
var yearDays = 365;
// force by days
var period = 86400000;
//Log(profits[0], profits[10]);
var ts = profits[0][3];
var te = profits[profits.length - 1][3];
var freeProfit = 0.03; // 0.04
var yearRange = yearDays * 86400000;
var totalReturns = profits[profits.length - 1][1] / totalAssets;
var annualizedReturns = (totalReturns * yearRange) / (te - ts);
// MaxDrawDown
var maxDrawdown = 0;
var maxAssets = totalAssets;
var maxAssetsTime = 0;
var maxDrawdownTime = 0;
var maxDrawdownStartTime = 0;
var winningRate = 0;
var winningResult = 0;
//var nowDrawdown = 0;
for (var i = 0; i < profits.length; i++) {
if (i == 0) {
if (profits[i][1] > 0) {
winningResult++;
}
} else {
if (profits[i][1] > profits[i - 1][1]) {
winningResult++;
}
}
if (profits[i][1] + totalAssets > maxAssets) {
maxAssets = profits[i][1] + totalAssets;
maxAssetsTime = profits[i][3];
}
if (maxAssets > 0) {
var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets;
if (drawDown > maxDrawdown) {
maxDrawdown = drawDown;
maxDrawdownTime = profits[i][3];
maxDrawdownStartTime = maxAssetsTime;
}
}
}
if (profits.length > 0) {
winningRate = winningResult / profits.length;
}
//Log("最大资产",maxAssets,"最大资产时间",_D(maxAssetsTime),"当前资产",profits[profits.length - 1][1],"当前资产时间",_D(profits[profits.length - 1][1]))
var nowDrawdown = 1 - (profits[profits.length - 1][1] + totalAssets) / maxAssets;
if (nowDrawdown < 0) {
nowDrawdown = 0;
}
// trim profits
var i = 0;
var datas = [];
var sum = 0;
var preProfit = 0;
var perRatio = 0;
var rangeEnd = te;
if ((te - ts) % period > 0) {
rangeEnd = (parseInt(te / period) + 1) * period;
}
for (var n = ts; n < rangeEnd; n += period) {
var dayProfit = 0.0;
var cut = n + period;
while (i < profits.length && profits[i][3] < cut) {
dayProfit += profits[i][1] - preProfit;
preProfit = profits[i][1];
i++;
}
perRatio = ((dayProfit / totalAssets) * yearRange) / period;
sum += perRatio;
datas.push(perRatio);
}
var sharpeRatio = 0;
var volatility = 0;
if (datas.length > 0) {
var avg = sum / datas.length;
var std = 0;
for (i = 0; i < datas.length; i++) {
std += Math.pow(datas[i] - avg, 2);
}
volatility = Math.sqrt(std / datas.length);
if (volatility !== 0) {
sharpeRatio = (annualizedReturns - freeProfit) / volatility;
}
}
return {
totalAssets: totalAssets,
yearDays: yearDays,
totalReturns: totalReturns,
annualizedReturns: annualizedReturns,
sharpeRatio: sharpeRatio,
volatility: volatility,
nowDrawdown: nowDrawdown,
maxDrawdown: maxDrawdown,
maxDrawdownTime: maxDrawdownTime,
maxAssetsTime: maxAssetsTime,
maxDrawdownStartTime: maxDrawdownStartTime,
winningRate: winningRate,
nowDrawdownFormat: $.TimeBetween(maxAssetsTime, new Date()),
maxDrawdownFormat: $.TimeBetween(maxDrawdownStartTime, maxDrawdownTime),
};
};
//取第多少周
$.GetWeek = function (date) {
let nowDate = new Date(date);
let firstDay = new Date(date);
firstDay.setMonth(0); //设置1月
firstDay.setDate(1); //设置1号
let diffDays = Math.ceil((nowDate - firstDay) / (24 * 60 * 60 * 1000));
let week = Math.ceil(diffDays / 7);
week = week === 0 ? 1 : week;
let month = nowDate.getMonth() + 1;
if (month.toString().length == 1) {
month = "0" + month;
}
let ret = {
year: nowDate.getFullYear(),
month: month,
day: nowDate.getDate(),
week: week,
};
return ret;
};
function main() {}
Detail
https://www.fmz.com/strategy/277946
Last Modified
2022-03-24 15:51:13