update
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
搬运FMZ教程-JavaScript速成手册
|
||||
FMZ教程-JavaScript速成手册
|
||||
|
||||
> 策略作者
|
||||
|
||||
@@ -378,4 +378,4 @@ https://www.fmz.com/strategy/395725
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-05 17:04:51
|
||||
2023-01-16 09:43:09
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
搬运FMZ教程-Python速成手册
|
||||
FMZ教程-Python速成手册
|
||||
|
||||
> 策略作者
|
||||
|
||||
@@ -465,4 +465,4 @@ https://www.fmz.com/strategy/395727
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-05 17:04:56
|
||||
2023-01-16 09:43:03
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
HFT高频订单流因子
|
||||
|
||||
> 策略作者
|
||||
|
||||
发明者量化
|
||||
|
||||
> 策略描述
|
||||
|
||||
|
||||
一个入门级订单流高频alpha因子, 可以做为市商策略的最优买卖定价距离参考, 信号归一为[-1, 1], 趋向1表示买方市场,趋向-1则是卖方市场, 策略会实时绘制因子值与最后成交价
|
||||
策略使用OKX与币安期货websocket接口接收计算, 下图是指标效果, 可以看出有一定的有效性, 公开给高频入门的量化爱好者
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
> 策略参数
|
||||
|
||||
|
||||
|
||||
|参数|默认值|描述|
|
||||
|----|----|----|
|
||||
|QSize|100|QSize|
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
let _chart = Chart({
|
||||
subtitle: {
|
||||
text: "Market Status",
|
||||
},
|
||||
yAxis: [{
|
||||
height: "60%",
|
||||
lineWidth: 1,
|
||||
title: {
|
||||
text: 'Close',
|
||||
},
|
||||
opposite: true,
|
||||
labels: {
|
||||
align: "right",
|
||||
x: -3,
|
||||
}
|
||||
}, {
|
||||
title: {
|
||||
text: 'Alpha',
|
||||
},
|
||||
top: "60%",
|
||||
height: "20%",
|
||||
offset: 0,
|
||||
lineWidth: 1
|
||||
}, {
|
||||
title: {
|
||||
text: 'Vol',
|
||||
},
|
||||
top: "80%",
|
||||
height: "20%",
|
||||
offset: 0,
|
||||
lineWidth: 1
|
||||
}],
|
||||
|
||||
series: [{
|
||||
name: 'Last',
|
||||
lineWidth: 1,
|
||||
data: [],
|
||||
id: 'primary',
|
||||
tooltip: {
|
||||
xDateFormat: '%Y-%m-%d %H:%M:%S'
|
||||
},
|
||||
yAxis: 0
|
||||
}, {
|
||||
type: 'column',
|
||||
lineWidth: 2,
|
||||
name: 'Alpha',
|
||||
data: [],
|
||||
yAxis: 1,
|
||||
color: 'green',
|
||||
zones: [{
|
||||
value: 0,
|
||||
color: 'red'
|
||||
}]
|
||||
}, {
|
||||
lineWidth: 1,
|
||||
type: 'area',
|
||||
color: '#257ed4',
|
||||
name: 'Vol',
|
||||
data: [],
|
||||
yAxis: 2
|
||||
}],
|
||||
})
|
||||
|
||||
function calc_alpha(trades) {
|
||||
let tick_sell_vol = 0
|
||||
let tick_buy_vol = 0
|
||||
let last_buy_vol = 0
|
||||
let last_sell_vol = 0
|
||||
let rightPos = Math.ceil(trades.length * 0.382)
|
||||
trades.forEach(function(trade, idx) {
|
||||
if (trade.side == 'buy') {
|
||||
if (idx >= rightPos) {
|
||||
last_buy_vol += trade.qty
|
||||
}
|
||||
tick_buy_vol += trade.qty
|
||||
} else {
|
||||
if (idx >= rightPos) {
|
||||
last_sell_vol += trade.qty
|
||||
}
|
||||
tick_sell_vol += trade.qty
|
||||
}
|
||||
})
|
||||
|
||||
let tanh = function(x) {
|
||||
// return [-1, 1]
|
||||
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x))
|
||||
}
|
||||
|
||||
let positive_ratio = last_buy_vol / tick_sell_vol
|
||||
let negative_ratio = last_sell_vol / tick_buy_vol
|
||||
let trade_ratio = 0
|
||||
if (positive_ratio > negative_ratio) {
|
||||
trade_ratio = tanh(positive_ratio)
|
||||
} else {
|
||||
trade_ratio = tanh(-negative_ratio)
|
||||
}
|
||||
return _N(trade_ratio, 3)
|
||||
}
|
||||
|
||||
let _trades = []
|
||||
let _vol = 0
|
||||
|
||||
function onTick(ctx, event) {
|
||||
if (event.trades) {
|
||||
event.trades.forEach(function(trade) {
|
||||
_vol += trade.qty
|
||||
_trades.push(trade)
|
||||
if (_trades.length > QSize) {
|
||||
_trades.shift()
|
||||
}
|
||||
})
|
||||
if (_trades.length >= QSize) {
|
||||
let val = calc_alpha(_trades)
|
||||
_chart.add(0, [event.ts, _trades[_trades.length-1].price])
|
||||
_chart.add(1, [event.ts, val])
|
||||
_chart.add(2, [event.ts, _vol])
|
||||
_vol = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
let ctName = "swap"
|
||||
_chart.reset()
|
||||
let ctx = $.NewWSS(exchange, function(ws, e) {
|
||||
let msg = null
|
||||
if (e.GetName() == 'Futures_OKCoin') {
|
||||
msg = {
|
||||
op: "subscribe",
|
||||
args: []
|
||||
}
|
||||
let instId = e.SetContractType(ctName).InstrumentID
|
||||
msg.args.push({
|
||||
channel: "books5",
|
||||
instId: instId
|
||||
})
|
||||
msg.args.push({
|
||||
channel: "trades",
|
||||
instId: instId
|
||||
})
|
||||
} else {
|
||||
msg = {
|
||||
method: "SUBSCRIBE",
|
||||
params: [],
|
||||
id: "1"
|
||||
}
|
||||
let symbol = e.GetCurrency().replace('_', '').toLowerCase()
|
||||
msg.params.push(symbol + "@aggTrade")
|
||||
msg.params.push(symbol + "@depth20@100ms")
|
||||
}
|
||||
ws.write(JSON.stringify(msg))
|
||||
Log("subscribe", msg, "channel")
|
||||
LogStatus("Ready")
|
||||
}, onTick, false)
|
||||
|
||||
while (true) {
|
||||
ctx.poll()
|
||||
EventLoop(1000)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/392784
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-02-01 19:43:36
|
||||
+42
-29
@@ -11,18 +11,18 @@ OKX&Binance Websocket高频交易模板 (多品种)||OKEX & Binance Websocket Hi
|
||||
|
||||
[trans]
|
||||
实现功能:
|
||||
1. 公共流订阅, trades及深度合成
|
||||
2. 私有流订阅, 维护本地委托单与仓位以及余额信息
|
||||
3. 维护取消订单超时状态, 支持OKX的amendOrders修改订单
|
||||
4. 支持多个品种, 方便高频策略以最低的延迟同时操作多个市场
|
||||
5. 添加函数 EventLoop(需要最新托管者支持), 此函数可以在多个websocket连接的情况下, 等待任意websocket数据返回, 避免轮询
|
||||
6. 支持OKX与Binance期货与Binance的现货与现货杠杆交易, OKX的现货暂未加入支持, 感兴趣的可以自己更改一下
|
||||
7. OKX的私有流订阅需要Key与密码已经做为参数写在模板里
|
||||
8. 自动处理断线重连等一些基本的网络功能
|
||||
9. 支持私有流订单成交取消回报的事件回调
|
||||
10. 统一两个交易所的下单逻辑, 具体可以看模板源码或者例子
|
||||
11. 支持同时订阅多个交易所的websocket接口
|
||||
12. 订单的报单修改以及删除可以批量做为任务返回, 会自动处理交易任务
|
||||
* 公共流订阅, trades及深度合成
|
||||
* 私有流订阅, 维护本地委托单与仓位以及余额信息
|
||||
* 维护取消订单超时状态, 支持OKX的amendOrders修改订单
|
||||
* 支持多个品种, 方便高频策略以最低的延迟同时操作多个市场
|
||||
* 添加函数 EventLoop(需要最新托管者支持), 此函数可以在多个websocket连接的情况下, 等待任意websocket数据返回, 避免轮询
|
||||
* 支持OKX与Binance期货与Binance的现货与现货杠杆交易, OKX的现货暂未加入支持, 感兴趣的可以自己更改一下
|
||||
* OKX的私有流订阅需要Key与密码已经做为参数写在模板里
|
||||
* 自动处理断线重连等一些基本的网络功能
|
||||
* 支持私有流订单成交取消回报的事件回调
|
||||
* 统一两个交易所的下单逻辑, 具体可以看模板源码或者例子
|
||||
* 支持同时订阅多个交易所的websocket接口
|
||||
* 订单的报单修改以及删除可以批量做为任务返回, 会自动处理交易任务
|
||||
|
||||
高频下单的时候,交易所返回的定单会不及时(private通道),但这时侯行情可能已经变化,我们需要本地维护一个订单状态, 策略已经实现,
|
||||
模板会自动识别是OKX还是Binance, 下面是一个简单的例子, 强烈建议阅读源码,这样能更深层次的定制你自己的功能
|
||||
@@ -132,7 +132,7 @@ function main() {
|
||||
|
||||
while (true) {
|
||||
ctx.poll()
|
||||
__syscall("TSocket_WaitAny", 1000)
|
||||
EventLoop(1000)
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -539,6 +539,11 @@ function NewOKXWebSocketPrivate(ctx, verbose) {
|
||||
}
|
||||
|
||||
self.poll = function(timeout) {
|
||||
|
||||
if (AccessKey.length == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
let ts = new Date().getTime()
|
||||
if (self.lastPing == 0) {
|
||||
self.lastPing = ts
|
||||
@@ -610,11 +615,13 @@ function NewOKXWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
|
||||
let self = {
|
||||
e: e,
|
||||
key: e.GetName() + '/' + e.GetCurrency(),
|
||||
quoteCurrency: e.GetQuoteCurrency(),
|
||||
name: e.GetName(),
|
||||
verbose: verbose,
|
||||
isFutures: e.GetName().indexOf("Futures_") == 0,
|
||||
ws: null,
|
||||
cache: {},
|
||||
channles: [],
|
||||
depthCount: 0,
|
||||
depthConsumed: 0,
|
||||
@@ -623,7 +630,6 @@ function NewOKXWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
asks: {},
|
||||
bids: {}
|
||||
},
|
||||
trades: [],
|
||||
lastMarket: 0
|
||||
}
|
||||
self.wsPrivate = NewOKXWebSocketPrivate(self, verbose)
|
||||
@@ -655,7 +661,7 @@ function NewOKXWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
} else if (obj.event == 'login') {
|
||||
self.channles = []
|
||||
if (typeof(onLogin) === 'function') {
|
||||
onLogin(self.ws)
|
||||
onLogin(self.ws, self.e)
|
||||
}
|
||||
} else {
|
||||
self.lastMarket = new Date().getTime();
|
||||
@@ -786,17 +792,23 @@ function NewOKXWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
if (!self.ws) {
|
||||
return
|
||||
}
|
||||
let tsStr = (new Date().getTime() / 1000).toString()
|
||||
let authMsg = {
|
||||
"op": "login",
|
||||
"args": [{
|
||||
"apiKey": AccessKey,
|
||||
"passphrase": Passphrase,
|
||||
"timestamp": tsStr,
|
||||
"sign": self.e.HMAC("sha256", "base64", tsStr + "GET" + "/users/self/verify", "{{secretkey}}")
|
||||
}]
|
||||
if (AccessKey.length == 0) {
|
||||
if (typeof(onLogin) === 'function') {
|
||||
onLogin(self.ws, self.e)
|
||||
}
|
||||
} else {
|
||||
let tsStr = (new Date().getTime() / 1000).toString()
|
||||
let authMsg = {
|
||||
"op": "login",
|
||||
"args": [{
|
||||
"apiKey": AccessKey,
|
||||
"passphrase": Passphrase,
|
||||
"timestamp": tsStr,
|
||||
"sign": self.e.HMAC("sha256", "base64", tsStr + "GET" + "/users/self/verify", "{{secretkey}}")
|
||||
}]
|
||||
}
|
||||
self.ws.write(JSON.stringify(authMsg))
|
||||
}
|
||||
self.ws.write(JSON.stringify(authMsg))
|
||||
}
|
||||
if (!self.ws) {
|
||||
return
|
||||
@@ -1286,16 +1298,17 @@ function NewBinanceSocketPrivate(ctx, verbose) {
|
||||
function NewBinanceWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
let self = {
|
||||
e: e,
|
||||
key: e.GetName() + '/' + e.GetCurrency(),
|
||||
quoteCurrency: e.GetQuoteCurrency(),
|
||||
name: e.GetName(),
|
||||
isFutures: e.GetName().indexOf("Futures_") == 0,
|
||||
verbose: verbose,
|
||||
ws: null,
|
||||
cache: {},
|
||||
depthCount: 0,
|
||||
depthConsumed: 0,
|
||||
lastPing: 0,
|
||||
isReadyDic: {},
|
||||
trades: []
|
||||
isReadyDic: {}
|
||||
}
|
||||
self.base = self.isFutures ? "wss://fstream.binance.com/ws" : "wss://stream.binance.com/ws"
|
||||
|
||||
@@ -1407,7 +1420,7 @@ function NewBinanceWebSocketPublic(e, onLogin, onTick, verbose) {
|
||||
Log("Dial: ", self.base)
|
||||
self.ws = Dial(self.base)
|
||||
if (self.ws) {
|
||||
onLogin(self.ws)
|
||||
onLogin(self.ws, self.e)
|
||||
}
|
||||
}
|
||||
if (!self.ws) {
|
||||
@@ -1560,4 +1573,4 @@ https://www.fmz.com/strategy/395045
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-11 16:16:25
|
||||
2023-02-02 20:12:19
|
||||
|
||||
@@ -4,18 +4,26 @@
|
||||
> 开源策略
|
||||
|
||||
|
||||
- [Utility - Logger](https://www.fmz.com/strategy/209236)
|
||||
- [OKX&Binance Websocket高频交易模板 (多品种)||OKEX & Binance Websocket High-Frequency Multi-Symbols Trading Template](https://www.fmz.com/strategy/395045)
|
||||
- [HFT高频订单流因子](https://www.fmz.com/strategy/392784)
|
||||
- [Uniswap V3 交易类库|Uniswap V3 Trade Template](https://www.fmz.com/strategy/397260)
|
||||
- [定投止盈脚本](https://www.fmz.com/strategy/396182)
|
||||
- [pine语言学习脚本](https://www.fmz.com/strategy/395433)
|
||||
- [FMZ教程-JavaScript速成手册](https://www.fmz.com/strategy/395725)
|
||||
- [FMZ教程-Python速成手册](https://www.fmz.com/strategy/395727)
|
||||
- [【作手君分享】-ATR为例均值计算中容错教程](https://www.fmz.com/strategy/396764)
|
||||
- [【作手君分享】-ADX值达到条件进行通知](https://www.fmz.com/strategy/396762)
|
||||
- [【作手君分享】-逐棒分析多空强弱指示器](https://www.fmz.com/strategy/396760)
|
||||
- [ZT 交易所接口,可用于对接【平台暂不支持的冷门交易所】 ZT](https://www.fmz.com/strategy/396040)
|
||||
- [Exit from specific entries](https://www.fmz.com/strategy/395966)
|
||||
- [Highest high/lowest low stop](https://www.fmz.com/strategy/395962)
|
||||
- [搬运FMZ教程-Python速成手册](https://www.fmz.com/strategy/395727)
|
||||
- [搬运FMZ教程-JavaScript速成手册](https://www.fmz.com/strategy/395725)
|
||||
- [pine语言学习脚本](https://www.fmz.com/strategy/395433)
|
||||
- [Utility - Logger](https://www.fmz.com/strategy/209236)
|
||||
- [标准上涨五浪下跌五浪策略](https://www.fmz.com/strategy/395584)
|
||||
- [MACD逃顶策略](https://www.fmz.com/strategy/356399)
|
||||
- [随机数猜大猜小](https://www.fmz.com/strategy/394112)
|
||||
- [MACD Strategy](https://www.fmz.com/strategy/392636)
|
||||
- [TradingView信号执行策略2(教学)](https://www.fmz.com/strategy/392048)
|
||||
- [ddddddd](https://www.fmz.com/strategy/392108)
|
||||
- [SSL CHANNEL + STOCH RSI](https://www.fmz.com/strategy/391341)
|
||||
- [SSL Hybrid + STOCH RSI](https://www.fmz.com/strategy/391080)
|
||||
- [大道至简系列1--30行代码实现马丁带止损策略,ETH回测年化65%,功能齐全](https://www.fmz.com/strategy/381941)
|
||||
@@ -299,7 +307,6 @@
|
||||
- [AlphaTrend use mfi](https://www.fmz.com/strategy/360014)
|
||||
- [Sentiment Oscillator](https://www.fmz.com/strategy/361332)
|
||||
- [【币安多交易对】 现货 用来市价清仓用的](https://www.fmz.com/strategy/360782)
|
||||
- [简单马丁格尔(btc合约)](https://www.fmz.com/strategy/270689)
|
||||
- [【币安】【多交易对】价格区间提醒](https://www.fmz.com/strategy/342165)
|
||||
- [数字货币现货打新抢币策略(教学)](https://www.fmz.com/strategy/358383)
|
||||
- [布林马丁测试版V1.4](https://www.fmz.com/strategy/345504)
|
||||
|
||||
File diff suppressed because one or more lines are too long
+141
-92
@@ -24,7 +24,7 @@ btcvegas
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
|
||||
// fmz@9b3674e14505be59c439796e5f78dc8c
|
||||
|
||||
//var COLOR_ERROR = "#FF0000"
|
||||
//var COLOR_WARN = "#FF0000"
|
||||
@@ -37,37 +37,37 @@ var LEVER_PATTERN = {
|
||||
ERROR: 3
|
||||
}
|
||||
|
||||
$.changeLoggerLever = function(val){
|
||||
$.changeLoggerLever = function (val) {
|
||||
level = val
|
||||
}
|
||||
|
||||
//var loggerLever = [LEVER_PATTERN.DEBUG, LEVER_PATTERN.INFO, LEVER_PATTERN.WARNING, LEVER_PATTERN.ERROR][level]
|
||||
$.Error = function(msg, obj, route='route') {
|
||||
if (level == 0 || "route" + routeFilter == route){
|
||||
$.Error = function (msg, obj, route = 'route') {
|
||||
if (level == 0 || "route" + routeFilter == route) {
|
||||
Log('[ERR] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$.Warn = function(msg, obj, route='route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route){
|
||||
$.Warn = function (msg, obj, route = 'route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route) {
|
||||
if (level <= LEVER_PATTERN.WARNING) {
|
||||
Log('[WAR] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.Info = function(msg, obj, route='route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route){
|
||||
$.Info = function (msg, obj, route = 'route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route) {
|
||||
if (level <= LEVER_PATTERN.INFO) {
|
||||
Log('[INF] ', "[" + route.toUpperCase() + "]" , msg, obj, '#0000FF')
|
||||
Log('[INF] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$.Debug = function(msg, obj, route='route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route){
|
||||
$.Debug = function (msg, obj, route = 'route') {
|
||||
if (routeFilter == 0 || "route" + routeFilter == route) {
|
||||
if (level <= LEVER_PATTERN.DEBUG) {
|
||||
Log('[DBG] ', "[" + route.toUpperCase() + "]", msg, obj, '#0000FF')
|
||||
}
|
||||
@@ -76,6 +76,7 @@ $.Debug = function(msg, obj, route='route') {
|
||||
|
||||
var executedBlocksCross = []
|
||||
var executedBlocksCrossIds = []
|
||||
var takerExecutionSummary = []
|
||||
var executedTrades = []
|
||||
var blocksLatency = []
|
||||
var blocksLatencyV2 = []
|
||||
@@ -94,7 +95,7 @@ var tradesTable = {
|
||||
var latencyTable = {
|
||||
type: 'table',
|
||||
title: 'Timestamps',
|
||||
cols: ['Label-Id', 'Exch-Mkr', 'Start', 'End', 'Mkr-Live', 'Cancel-Mkr', 'Cancel-Exec', 'Creating-Tkr', 'Tkr-Live', 'Complete'],
|
||||
cols: ['Label-Id', 'Exch-Mkr', 'Start', 'End', 'Book-T', 'Book-M', 'Mkr-Live', 'Cancel-Mkr', 'Cancel-Exec', 'Creating-Tkr', 'Tkr-Live', 'Complete'],
|
||||
rows: blocksLatencyV2
|
||||
}
|
||||
|
||||
@@ -126,6 +127,13 @@ var blocksTable = {
|
||||
rows: executedBlocksCross
|
||||
}
|
||||
|
||||
var blocksTakerSummary = {
|
||||
type: 'table',
|
||||
title: 'Taker Exec',
|
||||
cols: ['Label-Id', 'Exch-B', 'Slip-%', 'Book-T', 'Book-M', 'Taker-Liq', 'Taker-Px-Init', 'Taker-Px-Sent'],
|
||||
rows: takerExecutionSummary
|
||||
}
|
||||
|
||||
var tradesTable_triangular = {
|
||||
type: 'table',
|
||||
title: 'Executed Blocks',
|
||||
@@ -148,7 +156,7 @@ var currentStatusTable = {
|
||||
|
||||
*/
|
||||
|
||||
$.logBotStatus = function(){
|
||||
$.logBotStatus = function () {
|
||||
currentStatus.push(
|
||||
[
|
||||
new Date().toLocaleString("da-DK"), // Timestamp
|
||||
@@ -171,57 +179,57 @@ $.logBotStatus = function(){
|
||||
3- REST Update -> bot had to check status via rest.
|
||||
*/
|
||||
|
||||
$.logArbProfit = function(makerTrade, takerTrade, conversionPrice, route, conversionTrade=null) {
|
||||
if (makerTrade.side == 0 || makerTrade.side == "Buy"){
|
||||
$.logArbProfit = function (makerTrade, takerTrade, conversionPrice, route, conversionTrade = null) {
|
||||
if (makerTrade.side == 0 || makerTrade.side == "Buy") {
|
||||
buyTrade = makerTrade
|
||||
sellTrade = takerTrade
|
||||
}
|
||||
else if (makerTrade.side == 1 || makerTrade.side == "Sell"){
|
||||
else if (makerTrade.side == 1 || makerTrade.side == "Sell") {
|
||||
buyTrade = takerTrade
|
||||
sellTrade = makerTrade
|
||||
}
|
||||
else if (takerTrade.side == 0 || takerTrade.side == "Buy"){
|
||||
else if (takerTrade.side == 0 || takerTrade.side == "Buy") {
|
||||
buyTrade = takerTrade
|
||||
sellTrade = makerTrade
|
||||
}
|
||||
else if (takerTrade.side == 1 || takerTrade.side == "Sell"){
|
||||
else if (takerTrade.side == 1 || takerTrade.side == "Sell") {
|
||||
buyTrade = makerTrade
|
||||
sellTrade = takerTrade
|
||||
}
|
||||
|
||||
tradeSpread = 0
|
||||
if(conversionTrade){
|
||||
if (conversionTrade) {
|
||||
tradeSpread = tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade)
|
||||
}
|
||||
else {
|
||||
tradeSpread = tradeSpreadCross(buyTrade, sellTrade, route)
|
||||
}
|
||||
|
||||
if (tradeSpread > -50 && tradeSpread < 200){
|
||||
if (tradeSpread > -50 && tradeSpread < 200) {
|
||||
LogProfit(tradeSpread)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$.logBlockTrades = function(makerTrade, takerTrade, conversionTrade, labelId, loc, route, lat_mkr, lat_trk, lat_mkr_cancel, lat_cyc, tries, premiumTarget, discountTarget) {
|
||||
$.logBlockTrades = function (makerTrade, takerTrade, conversionTrade, labelId, loc, route, lat_mkr, lat_trk, lat_mkr_cancel, lat_cyc, tries, premiumTarget, discountTarget) {
|
||||
if (conversionTrade) {
|
||||
logTradesTriangular(makerTrade, takerTrade, conversionTrade, labelId, loc, lat)
|
||||
}
|
||||
}
|
||||
else if (takerTrade && makerTrade) {
|
||||
logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_trk, lat_cyc, tries, premiumTarget, discountTarget)
|
||||
$.logLatency(labelId, makerTrade.exchange, lat_mkr, lat_trk, lat_mkr_cancel, lat_cyc)
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
else {
|
||||
$.Warn("[Utility Logger] Cannot Log Trade", takerTrade)
|
||||
}
|
||||
}
|
||||
|
||||
$.logExecutions = function(trade, exchange){
|
||||
$.logExecutions = function (trade, exchange) {
|
||||
var date = Date.now().toLocaleString()
|
||||
|
||||
if (trade.DealAmount > 0){
|
||||
executedTrades.push(
|
||||
if (trade.DealAmount > 0) {
|
||||
// insert to executed Trades
|
||||
executedTrades.splice(0, 0,
|
||||
[
|
||||
date.substring(0, date.length - 3),
|
||||
trade.label,
|
||||
@@ -234,46 +242,86 @@ $.logExecutions = function(trade, exchange){
|
||||
trade.fees
|
||||
]
|
||||
)
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
// updates executed Blocks Cross if order found
|
||||
for (block of executedBlocksCross) {
|
||||
if (trade.label == block[1] && trade.label != null) {
|
||||
if (trade.Type == "Buy") {
|
||||
block[7] = trade.AvgPrice // Price
|
||||
block[9] = trade.DealAmount // Amount
|
||||
block[5] = _N(block[8] - trade.AvgPrice, 4) // Spread Nominal
|
||||
block[3] = _N(((block[8] / trade.AvgPrice - 1) * 100), 3) // Spread %
|
||||
block[6] = _N((block[8] * block[10]) - (trade.AvgPrice * trade.DealAmount), 2) // Value
|
||||
}
|
||||
else if (trade.Type == "Sell") {
|
||||
block[8] = trade.AvgPrice
|
||||
block[10] = trade.DealAmount
|
||||
block[5] = _N(trade.AvgPrice - block[7], 4) // Spread Nominal
|
||||
block[3] = _N(((trade.AvgPrice / block[7] - 1) * 100), 3) // Spread %
|
||||
block[6] = _N((trade.AvgPrice * trade.DealAmount) - (block[7] * block[9]), 2)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$.logPosition = function(exch1, exch2, exh1pos, exch2pos){
|
||||
positionHistory.push(
|
||||
$.logPosition = function (exch1, exch2, exh1pos, exch2pos) {
|
||||
positionHistory.splice(0, 0,
|
||||
[
|
||||
new Date().toLocaleString("da-DK"),
|
||||
exch1,
|
||||
exch1,
|
||||
exch2,
|
||||
exh1pos,
|
||||
exch2pos,
|
||||
exch2pos,
|
||||
_N(exh1pos + exch2pos, 3)
|
||||
|
||||
]
|
||||
)
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
|
||||
$.logVolume = function(exch1, exch2, amt1, amt2){
|
||||
$.logTakerExecutionSummary = function (labelId, exchange, orderbook_latency_taker, orderbook_latency_maker, taker_liquidity, taker_price_init, taker_price_sent) {
|
||||
takerExecutionSummary.splice(0, 0,
|
||||
[
|
||||
labelId,
|
||||
exchange.GetName(),
|
||||
0,
|
||||
orderbook_latency_taker,
|
||||
orderbook_latency_maker,
|
||||
taker_liquidity,
|
||||
taker_price_init,
|
||||
taker_price_sent
|
||||
]
|
||||
)
|
||||
|
||||
var volExchange1 = _G("accumulatedVolume"+ exch1) + amt1
|
||||
var volExchange2 = _G("accumulatedVolume"+ exch2) + amt2
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
|
||||
volumeHistory.push(
|
||||
$.logVolume = function (exch1, exch2, amt1, amt2) {
|
||||
|
||||
var volExchange1 = _G("accumulatedVolume" + exch1) + amt1
|
||||
var volExchange2 = _G("accumulatedVolume" + exch2) + amt2
|
||||
|
||||
volumeHistory.splice(0, 0,
|
||||
[
|
||||
new Date().toLocaleString("da-DK"),
|
||||
exch1,
|
||||
exch1,
|
||||
exch2,
|
||||
_N(amt1, 2),
|
||||
_N(amt1, 2),
|
||||
_N(amt2, 2),
|
||||
_N(volExchange1, 2),
|
||||
_N(volExchange2, 2)
|
||||
]
|
||||
)
|
||||
|
||||
_G("accumulatedVolume" + exch1, volExchange1),
|
||||
_G("accumulatedVolume" + exch2, volExchange2)
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
_G("accumulatedVolume" + exch1, volExchange1),
|
||||
_G("accumulatedVolume" + exch2, volExchange2)
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
|
||||
/* Latencies measured.
|
||||
@@ -285,83 +333,86 @@ $.logVolume = function(exch1, exch2, amt1, amt2){
|
||||
Full Cycle Latency -> Composite latency from moment of transaction notification to full taker liquidation. CANCELLED_EXECUTION to START.
|
||||
*/
|
||||
|
||||
$.logLatency = function (labelId, exchange, lat_mkr, lat_tkr, lat_mkr_cancel, lat_cyc, lat_er=0, lat_react=0){
|
||||
|
||||
blocksLatency.push(
|
||||
$.logLatency = function (labelId, exchange, lat_mkr, lat_tkr, lat_mkr_cancel, lat_cyc, lat_er = 0, lat_react = 0) {
|
||||
|
||||
blocksLatency.splice(0, 0,
|
||||
[
|
||||
labelId,
|
||||
exchange.GetName(),
|
||||
lat_mkr,
|
||||
labelId,
|
||||
exchange.GetName(),
|
||||
lat_mkr,
|
||||
lat_mkr_cancel,
|
||||
lat_er,
|
||||
lat_er,
|
||||
lat_tkr,
|
||||
lat_react,
|
||||
lat_cyc
|
||||
]
|
||||
)
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
}
|
||||
|
||||
$.logTimestamps = function(labelId, exchange, loc, start, creating_maker, maker_live, cancelling_maker, cancelled_execution, creating_taker, taker_live, process_execution){
|
||||
$.logTimestamps = function (labelId, exchange, loc, start, creating_maker, maker_live, cancelling_maker, cancelled_execution, creating_taker, taker_live, process_execution, orderbook_latency_taker, orderbook_latency_maker) {
|
||||
|
||||
// If order is executed before the bot tries to cancel these status are irrelevante
|
||||
if (loc < 2){
|
||||
if (loc < 2) {
|
||||
cancelling_maker = maker_live
|
||||
cancelled_execution = maker_live
|
||||
}
|
||||
|
||||
blocksLatencyV2.push(
|
||||
blocksLatencyV2.splice(0, 0,
|
||||
[
|
||||
labelId,
|
||||
labelId,
|
||||
exchange.GetName(),
|
||||
start,
|
||||
process_execution,
|
||||
orderbook_latency_taker,
|
||||
orderbook_latency_maker,
|
||||
maker_live - creating_maker,
|
||||
cancelling_maker - maker_live,
|
||||
cancelled_execution - cancelling_maker,
|
||||
creating_taker - cancelled_execution,
|
||||
taker_live - creating_taker,
|
||||
process_execution - taker_live
|
||||
process_execution - taker_live,
|
||||
|
||||
|
||||
]
|
||||
)
|
||||
|
||||
LogStatus('`' + JSON.stringify([blocksTable, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable]) + '`')
|
||||
LogStatus('`' + JSON.stringify([blocksTable, blocksTableIds, tradesTable, posTable, volumeTable, latencyTable, currentStatusTable, blocksTakerSummary]) + '`')
|
||||
|
||||
}
|
||||
|
||||
function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, lat_cyc, tries, premiumTarget, discountTarget){
|
||||
function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, lat_cyc, tries, premiumTarget, discountTarget) {
|
||||
|
||||
if (makerTrade.side == 0 || makerTrade.side == "Buy"){
|
||||
if (makerTrade.side == 0 || makerTrade.side == "Buy") {
|
||||
buyTrade = makerTrade
|
||||
sellTrade = takerTrade
|
||||
buyExchange = makerTrade.exchange.GetName()
|
||||
sellExchange = takerTrade.exchange.GetName()
|
||||
}
|
||||
else if (makerTrade.side == 1 || makerTrade.side == "Sell"){
|
||||
else if (makerTrade.side == 1 || makerTrade.side == "Sell") {
|
||||
buyTrade = takerTrade
|
||||
sellTrade = makerTrade
|
||||
buyExchange = takerTrade.exchange.GetName()
|
||||
sellExchange = makerTrade.exchange.GetName()
|
||||
}
|
||||
else if (takerTrade.side == 0 || takerTrade.side == "Buy"){
|
||||
else if (takerTrade.side == 0 || takerTrade.side == "Buy") {
|
||||
buyTrade = takerTrade
|
||||
sellTrade = makerTrade
|
||||
buyExchange = makerTrade.exchange.GetName()
|
||||
sellExchange = takerTrade.exchange.GetName()
|
||||
}
|
||||
else if (takerTrade.side == 1 || takerTrade.side == "Sell"){
|
||||
else if (takerTrade.side == 1 || takerTrade.side == "Sell") {
|
||||
buyTrade = makerTrade
|
||||
sellTrade = takerTrade
|
||||
buyExchange = takerTrade.exchange.GetName()
|
||||
sellExchange = makerTrade.exchange.GetName()
|
||||
}
|
||||
|
||||
if (route == "route1" || route == "route2"){
|
||||
if (route == "route1" || route == "route2") {
|
||||
targetSpread = premiumTarget
|
||||
}
|
||||
else if (route == "route3" || route == "route4"){
|
||||
else if (route == "route3" || route == "route4") {
|
||||
targetSpread = discountTarget
|
||||
}
|
||||
else {
|
||||
@@ -369,8 +420,8 @@ function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, la
|
||||
}
|
||||
|
||||
var executedSpread = tradeSpreadCross(buyTrade, sellTrade)
|
||||
|
||||
var cur_date = new Date()
|
||||
|
||||
var cur_date = new Date()
|
||||
//cur_date.setHours(d.getHours() - 4)
|
||||
|
||||
|
||||
@@ -380,10 +431,10 @@ function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, la
|
||||
buyExchange, // Buy exchange
|
||||
executedSpread, // Spread %
|
||||
tradeSlippage(executedSpread, targetSpread), // Slippage
|
||||
_N(sellTrade.price - buyTrade.price, 4), // Spread $
|
||||
_N(sellTrade.price - buyTrade.price, 5), // Spread $
|
||||
tradeValueCross(buyTrade, sellTrade), // Value $
|
||||
_N(buyTrade.price, 4), // Buy Price
|
||||
_N(sellTrade.price, 4), // Sell Price
|
||||
_N(buyTrade.price, 5), // Buy Price
|
||||
_N(sellTrade.price, 5), // Sell Price
|
||||
buyTrade.size, // Buy Size
|
||||
sellTrade.size, // Sell Size
|
||||
loc, // Location of liquidation initiation
|
||||
@@ -403,27 +454,27 @@ function logTradesCross(makerTrade, takerTrade, labelId, loc, route, lat_tkr, la
|
||||
route
|
||||
]
|
||||
|
||||
|
||||
|
||||
Log("blockIds", blockIds)
|
||||
|
||||
executedBlocksCross.push(blockData)
|
||||
executedBlocksCrossIds.push(blockIds)
|
||||
executedBlocksCross.splice(0, 0, blockData)
|
||||
executedBlocksCrossIds.splice(0, 0, blockIds)
|
||||
}
|
||||
|
||||
function tradeSpreadCross(buyTrade, sellTrade) {
|
||||
return _N(((sellTrade.price / buyTrade.price - 1) * 100), 3)
|
||||
}
|
||||
|
||||
function tradeValueCross(buyTrade, sellTrade){
|
||||
function tradeValueCross(buyTrade, sellTrade) {
|
||||
return _N((sellTrade.price * sellTrade.size) - (buyTrade.price * buyTrade.size), 2)
|
||||
}
|
||||
|
||||
function tradeSlippage(executedSpread, targetSpread){
|
||||
function tradeSlippage(executedSpread, targetSpread) {
|
||||
var result = executedSpread - targetSpread
|
||||
return _N(result, 2)
|
||||
}
|
||||
|
||||
function logTradesTriangular(makerTrade, takerTrade, conversionTrade, labelId, loc, lat){
|
||||
function logTradesTriangular(makerTrade, takerTrade, conversionTrade, labelId, loc, lat) {
|
||||
conversionPrice = _N(conversionTrade.price, 6)
|
||||
conversionSize = conversionTrade.size
|
||||
conversionId = conversionTrade.id
|
||||
@@ -431,37 +482,35 @@ function logTradesTriangular(makerTrade, takerTrade, conversionTrade, labelId, l
|
||||
executedTradesTriangular.push(
|
||||
[Date.now(),
|
||||
labelId,
|
||||
(makerTrade.side == 0 || makerTrade.side == "Sell" || makerTrade.side == "sell") ? "Buy" : "Sell",
|
||||
tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade),
|
||||
makerTrade.price,
|
||||
takerTrade.price,
|
||||
(makerTrade.side == 0 || makerTrade.side == "Sell" || makerTrade.side == "sell") ? "Buy" : "Sell",
|
||||
tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade),
|
||||
makerTrade.price,
|
||||
takerTrade.price,
|
||||
conversionPrice,
|
||||
makerTrade.size,
|
||||
takerTrade.size,
|
||||
makerTrade.size,
|
||||
takerTrade.size,
|
||||
conversionSize,
|
||||
makerTrade.id,
|
||||
takerTrade.id,
|
||||
conversionTrade.id,
|
||||
makerTrade.id,
|
||||
takerTrade.id,
|
||||
conversionTrade.id,
|
||||
loc,
|
||||
lat
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
function tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade){
|
||||
function tradeSpreadTriangular(makerTrade, takerTrade, conversionTrade) {
|
||||
var result = 0
|
||||
// if it is a triangular arbitrage trade
|
||||
if (conversionTrade && makerTrade && takerTrade) {
|
||||
if ((makerTrade.side == 1 || makerTrade.side == "Sell" || makerTrade.side == "sell")) {
|
||||
result = _N(((makerTrade.price / (takerTrade.price * conversionTrade.price) - 1) * 100), 2)
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = _N((((takerTrade.price * conversionTrade.price) / makerTrade.price - 1) * 100), 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
@@ -470,4 +519,4 @@ https://www.fmz.com/strategy/209236
|
||||
|
||||
> 更新时间
|
||||
|
||||
2022-12-31 01:48:56
|
||||
2023-02-02 21:40:56
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
ddddddd
|
||||
|
||||
> 策略作者
|
||||
|
||||
稻草人
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
function main() {
|
||||
var a=0
|
||||
while(1){
|
||||
|
||||
Log(a)
|
||||
LogStatus(a)
|
||||
a++
|
||||
Sleep(1000)
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/392108
|
||||
|
||||
> 更新时间
|
||||
|
||||
2022-11-28 21:37:27
|
||||
+5
-3
@@ -36,6 +36,8 @@ slowSMA = sma(close, slowLength)
|
||||
// 设置止盈止损
|
||||
longStop = strategy.position_avg_price * (1 - 0.01)
|
||||
shortStop = strategy.position_avg_price * (1 + 0.01)
|
||||
longlimit = strategy.position_avg_price * (1 + 0.01)
|
||||
shortlimit = strategy.position_avg_price * (1 - 0.01)
|
||||
|
||||
// 开仓条件
|
||||
longCondition = crossover(fastSMA, slowSMA)
|
||||
@@ -46,8 +48,8 @@ strategy.entry("Long", strategy.long, when=longCondition)
|
||||
strategy.entry("Short", strategy.short, when=shortCondition)
|
||||
|
||||
// 止盈止损
|
||||
strategy.exit("Long Stop", "Long", stop=longStop)
|
||||
strategy.exit("Short Stop", "Short", stop=shortStop)
|
||||
strategy.exit("Long Stop", "Long", stop=longStop,limit=longlimit)
|
||||
strategy.exit("Short Stop", "Short", stop=shortStop,limit=shortlimit)
|
||||
|
||||
```
|
||||
|
||||
@@ -57,4 +59,4 @@ https://www.fmz.com/strategy/395433
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-03 07:32:44
|
||||
2023-01-28 14:58:19
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
【作手君分享】-ADX值达到条件进行通知
|
||||
|
||||
> 策略作者
|
||||
|
||||
作手君
|
||||
|
||||
> 策略描述
|
||||
|
||||
为回馈FMZ平台与社区,进行策略&代码&思路&模板的分享
|
||||
|
||||
简介:
|
||||
调用ADX指标,达到一定条件进行FMZ通讯通知
|
||||
可以顺序轮询多交易对
|
||||
|
||||
欢迎合作交流,共同学习进步~
|
||||
v:haiyanyydss
|
||||
|
||||
> 策略参数
|
||||
|
||||
|
||||
|
||||
|参数|默认值|描述|
|
||||
|----|----|----|
|
||||
|P_interval_time|1000|轮询间隔(毫秒)|
|
||||
|P_contract|quarter|合约|
|
||||
|P_adx_len|50|ADX参数|
|
||||
|P_adx_val|10|微信通知触发值(ADX大于此值)|
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
/*backtest
|
||||
start: 2020-01-01 00:00:00
|
||||
end: 2021-02-02 00:00:00
|
||||
period: 1h
|
||||
basePeriod: 1h
|
||||
exchanges: [{"eid":"Futures_OKCoin","currency":"ETH_USD"},{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
|
||||
args: [["P_contract","quarter|quarter"],["P_contract_value","10|100"]]
|
||||
*/
|
||||
|
||||
/*
|
||||
为回馈FMZ平台与社区,进行策略&代码&思路&模板的分享
|
||||
|
||||
简介:
|
||||
调用ADX指标,达到一定条件进行FMZ通讯通知
|
||||
可以顺序轮询多交易对
|
||||
|
||||
欢迎合作交流,共同学习进步~
|
||||
v:haiyanyydss
|
||||
*/
|
||||
|
||||
function getPara(val, i){
|
||||
val = ""+val;
|
||||
var ret = val.split("|").length>i?val.split("|")[i]:val.split("|")[val.split("|").length-1];
|
||||
return ret.trim();
|
||||
}
|
||||
|
||||
function Trade(e){
|
||||
this.e = e;
|
||||
this.last_alert_time = 0;
|
||||
this.ontick = function(){
|
||||
var records = _C(this.e.GetRecords);
|
||||
var last_record = records[records.length-1];
|
||||
var adx = talib.ADX(records, this.adx_len);
|
||||
if(this.last_alert_time < last_record.Time && adx[adx.length-1] > this.adx_val){
|
||||
this.last_alert_time = last_record.Time;
|
||||
Log(this.e.GetCurrency(), this.contract, "adx值超过"+this.adx_val , new Date(), "@");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
LogReset();
|
||||
var tradeArr = [];
|
||||
for(var i in exchanges){
|
||||
var trade = new Trade(exchanges[i]);
|
||||
trade.adx_len = 1*getPara(P_adx_len, i);
|
||||
trade.adx_val = 1*getPara(P_adx_val, i);
|
||||
trade.contract = getPara(P_contract, i);
|
||||
trade.e.SetContractType(trade.contract);
|
||||
tradeArr.push(trade)
|
||||
}
|
||||
|
||||
while (true) {
|
||||
for(var i in tradeArr){
|
||||
Sleep(P_interval_time);
|
||||
tradeArr[i].ontick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/396762
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-16 09:32:01
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
【作手君分享】-ATR为例均值计算中容错教程
|
||||
|
||||
> 策略作者
|
||||
|
||||
作手君
|
||||
|
||||
> 策略描述
|
||||
|
||||
为回馈FMZ平台与社区,进行策略&代码&思路&模板的分享
|
||||
|
||||
简介:
|
||||
详细的均值计算步骤,以ATR为例。
|
||||
包含指标调用、数据点不足容错、意外数据错误容错等细节
|
||||
策略的重要是细节的把握。
|
||||
|
||||
欢迎合作交流,共同学习进步~
|
||||
v:haiyanyydss
|
||||
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
var arecords = _C(exchange.GetRecords, 300);
|
||||
var time = arecords[arecords.length - 1].Time
|
||||
var nowtime = time;
|
||||
var atremaarr = [];
|
||||
var Onoff = 0;
|
||||
|
||||
function main() {
|
||||
while (true) {
|
||||
//这里开始 把这段放循环里
|
||||
var Num = 50; //可以改,几根的平均值
|
||||
var records = _C(exchange.GetRecords, 300);
|
||||
var atr = TA.EMA(records, 9)
|
||||
nowtime = records[records.length - 1].Time
|
||||
if (nowtime > time || Onoff == 0) {
|
||||
atr = atr.slice(atr.length - (20 + Num));
|
||||
for (var i = 0; i < (atr.length - Num); i++) { //(atr.length-Num) 长度减掉周期 比如500根 前50根是不准的平均值 这里就取450
|
||||
var atremTEMP = 0; //计算求和的,初始设置为0
|
||||
for (var j = 0; j < Num; j++) { //求和
|
||||
atrTEMP = atr[i + j] > 0 ? atr[i + j] : 0; //剔除意外数据 ,大于O 取值,小于O 或者其他情况取值O
|
||||
atremTEMP += atrTEMP;
|
||||
}
|
||||
atremaarr.push(atremTEMP / Num); //把平均值P到数组
|
||||
}
|
||||
time = nowtime;
|
||||
Onoff += 1;
|
||||
Log("计算第:", Onoff, "次。");
|
||||
}
|
||||
//这里结算 把这段放循环里
|
||||
Sleep(3000)
|
||||
Log("最后一根:", _N(atremaarr[atremaarr.length - 1], 2)) //拿值
|
||||
//Log("最后第二根:", _N(atremaarr[atremaarr.length-2],2))
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/396764
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-16 09:36:42
|
||||
@@ -0,0 +1,117 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
【作手君分享】-逐棒分析多空强弱指示器
|
||||
|
||||
> 策略作者
|
||||
|
||||
作手君
|
||||
|
||||
> 策略描述
|
||||
|
||||
为回馈FMZ平台与社区,进行策略&代码&思路&模板的分享
|
||||
|
||||
简介:
|
||||
封包好的函数指标,可直接调用
|
||||
逐根K线分析
|
||||
通过比较K线自身收盘位置与最近两根K线关系衡量市场多空强弱。
|
||||
|
||||
大多数情况下我们观察价格运动只会注意收盘价或者本根K线的形态,如何以一种更好的方式阅读K线和理解多空的强弱是更深入研究的方向,本研究提出一种解决思路,将K线自身类型与本根K线和上跟K线位置比较进行多空力量编码,如图所示,本研究将K线定义为18种类型。其分类方式主要有两个,一是收盘位置(帮助确定单根K线观点),二是收盘比较(帮助确定联系的K线观点)。收盘位置可以帮助确定单根K线的观点,我们根据一条K线的收盘价在其最高价到最低价的区间内所处的位置,把它定义为高位收盘K线、中位收盘K线和低位收盘K线。每种位置收盘的K线又分为强势K线(收盘价>开盘价)与弱势K线(收盘价<开盘价),因此单根K线的类别总共有6种,分别为:高位收盘的强势K线;高位收盘的弱势K线;中位收盘的强势K线;中位收盘的弱势K线;低位收盘的强势K线;低位收盘的弱势K线。
|
||||

|
||||

|
||||

|
||||

|
||||
综上所述,将6种K线收盘关系与3种K线收盘比较相结合,总共产生18种K线强弱关系,将多头最强的K线编码为9将最弱的K线编码为-9,其余依次按强弱关系递进编码,结果如图
|
||||

|
||||
|
||||
欢迎合作交流,共同学习进步~
|
||||
v:haiyanyydss
|
||||
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
$.getClosezhubang = function(rds){
|
||||
var arrclose = [];
|
||||
var arropen = [];
|
||||
var arrhigh = [];
|
||||
var arrlow = [];
|
||||
var arrzhubang = [];
|
||||
|
||||
for(var i in rds){
|
||||
arrclose[i] = rds[i].Close;
|
||||
arropen[i] = rds[i].Open;
|
||||
arrhigh[i] = rds[i].High;
|
||||
arrlow[i] = rds[i].Low;
|
||||
|
||||
if(i>1){
|
||||
|
||||
if(arrclose[i] >= arrhigh[i-1]){
|
||||
|
||||
if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.09;
|
||||
}else if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.08;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.07;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.06;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.05;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.04;
|
||||
}
|
||||
|
||||
}
|
||||
else if(arrclose[i] < arrhigh[i-1] && arrclose[i] > arrlow[i-1]){
|
||||
|
||||
if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.03;
|
||||
}else if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.02;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*1.01;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.99;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.98;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.97;
|
||||
}
|
||||
|
||||
}
|
||||
else if(arrclose[i] <= arrlow[i-1]){
|
||||
|
||||
if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.96;
|
||||
}else if(arrclose[i] >= (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.95;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.94;
|
||||
}else if(arrclose[i] > (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < (arrhigh[i]-(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.93;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] >= arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.92;
|
||||
}else if(arrclose[i] <= (arrlow[i]+(arrhigh[i]-arrlow[i])/3) && arrclose[i] < arropen[i]){
|
||||
arrzhubang[i] = arrclose[i]*0.91;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
arrzhubang[i] = arrclose[i];
|
||||
}
|
||||
|
||||
}
|
||||
return arrzhubang;
|
||||
}
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/396760
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-16 09:22:57
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
定投止盈脚本
|
||||
|
||||
> 策略作者
|
||||
|
||||
Zer3192
|
||||
|
||||
|
||||
|
||||
> 策略参数
|
||||
|
||||
|
||||
|
||||
|参数|默认值|描述|
|
||||
|----|----|----|
|
||||
|v_input_1|5|最大损失百分比|
|
||||
|v_input_2|3|止盈值|
|
||||
|
||||
|
||||
> 源码 (PineScript)
|
||||
|
||||
``` javascript
|
||||
//@version=4
|
||||
|
||||
strategy("定投止盈", overlay=true)
|
||||
|
||||
//定义最大损失百分比
|
||||
maxLossPercent = input(title="最大损失百分比", type=float,defval=5)
|
||||
|
||||
//定义止盈数字
|
||||
stopProfitVal = input(title="止盈值", type=float, defval=3)
|
||||
|
||||
//主力合约做多头头寸
|
||||
longCondition = crossover(open, close) //主力合约以开盘价横向突破收盘价做多
|
||||
|
||||
if (longCondition)
|
||||
strategy.entry("Long", strategy.long, comment="Open Long")
|
||||
|
||||
//止损条件
|
||||
//if (strategy.position_size > 0)
|
||||
//strategy.exit("Exit long", stop=strategy.position_avg_price * (1 - maxLossPercent/100))
|
||||
|
||||
//止盈条件
|
||||
profitExit = strategy.position_avg_price + stopProfitVal
|
||||
if (strategy.position_size > 0)
|
||||
strategy.exit("Exit long", limit = profitExit)
|
||||
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/396182
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-29 09:49:34
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
标准上涨五浪下跌五浪策略
|
||||
|
||||
> 策略作者
|
||||
|
||||
Zer3192
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
> 源码 (PineScript)
|
||||
|
||||
``` javascript
|
||||
//@version=4
|
||||
// 标准上涨五浪下跌五浪策略
|
||||
// 顶1
|
||||
s1 = lowest(low, 5)
|
||||
// 底1
|
||||
b1 = highest(high, 5)
|
||||
// 顶2
|
||||
s2 = lowest(low[1], 5)
|
||||
// 底2
|
||||
b2 = highest(high[1], 5)
|
||||
// 顶3
|
||||
s3 = lowest(low[2], 5)
|
||||
// 底3
|
||||
b3 = highest(high[2], 5)
|
||||
// 顶4
|
||||
s4 = lowest(low[3], 5)
|
||||
// 底4
|
||||
b4 = highest(high[3], 5)
|
||||
// 顶5
|
||||
s5 = lowest(low[4], 5)
|
||||
// 底5
|
||||
b5 = highest(high[4], 5)
|
||||
|
||||
// 上涨五浪
|
||||
up_waves = (b1 > b2) and (b2 > b3) and (b3 > b4) and (b4 > b5)
|
||||
// 下跌五浪
|
||||
down_waves = (s1 < s2) and (s2 < s3) and (s3 < s4) and (s4 < s5)
|
||||
|
||||
// 交易条件
|
||||
if (up_waves)
|
||||
strategy.entry("long", strategy.long, 1, stop = low[4], comment = "long")
|
||||
|
||||
else if (down_waves)
|
||||
strategy.entry("short", strategy.short, 1, stop = high[4], comment = "short")
|
||||
|
||||
// 绘图
|
||||
plotshape(up_waves, style = shape.triangleup, location = location.belowbar, color=green, title="上涨五浪")
|
||||
plotshape(down_waves, style = shape.triangledown, location = location.abovebar, color=red, title="下跌五浪")
|
||||
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/395584
|
||||
|
||||
> 更新时间
|
||||
|
||||
2023-01-03 21:31:11
|
||||
@@ -1,106 +0,0 @@
|
||||
|
||||
> 策略名称
|
||||
|
||||
简单马丁格尔(btc合约)
|
||||
|
||||
> 策略作者
|
||||
|
||||
忠^L
|
||||
|
||||
> 策略描述
|
||||
|
||||
!!!!!!!温馨提示,本策略仅供学习使用,用于实盘必定爆仓!!!!!!!!!!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
简单马丁格尔
|
||||
原理就是输了加倍,直到赢到期望的收益为止
|
||||
因为是回测用的,所有下单都是市价单,实盘没跑过!!
|
||||
|
||||
2022.4.19修改:根据EMA144判断走低于均线则优先做空,高于均线则做多
|
||||
|
||||
|
||||
|
||||
> 源码 (javascript)
|
||||
|
||||
``` javascript
|
||||
/*
|
||||
本策略仅供学习使用,用于实盘后果自负
|
||||
*/
|
||||
|
||||
|
||||
var n = 0.001 //初始下单数
|
||||
var MarginLevel = 50 //合约杠杆
|
||||
var profit = 0.1 //期望收益 ,不能小于手续费
|
||||
|
||||
|
||||
//取随机数
|
||||
function sum(m, n) {
|
||||
var num = Math.floor(Math.random() * (m - n) + n);
|
||||
return num;
|
||||
}
|
||||
|
||||
function main() {
|
||||
exchange.SetContractType("swap")
|
||||
exchange.SetMarginLevel(MarginLevel)
|
||||
var position = []
|
||||
while (true) {
|
||||
position = exchange.GetPosition()
|
||||
if (position.length == 0) {
|
||||
|
||||
var records = exchange.GetRecords(PERIOD_H1)
|
||||
// 判断K线bar数量是否满足指标计算周期
|
||||
var ema = TA.EMA(records, 144)
|
||||
var ema144 = ema[ema.length - 1]
|
||||
var ticker = exchange.GetTicker()
|
||||
var nowPrice = ticker.Last
|
||||
Log(ema144)
|
||||
|
||||
|
||||
if (nowPrice <ema144) {
|
||||
exchange.SetDirection("sell")
|
||||
exchange.Sell(-1, n, "开空")
|
||||
}
|
||||
if (nowPrice > ema144) {
|
||||
exchange.SetDirection("buy")
|
||||
exchange.Buy(-1, n, "开多")
|
||||
}
|
||||
|
||||
}
|
||||
if (position.length > 0) {
|
||||
|
||||
if (position[0].Type == 0) {
|
||||
//盈利大于期望
|
||||
if (position[0].Profit > profit) {
|
||||
exchange.SetDirection("closebuy")
|
||||
exchange.Sell(-1, position[0].Amount)
|
||||
}
|
||||
//负盈利大于保证金 则加仓
|
||||
|
||||
if (position[0].Profit < position[0].Margin * -1) {
|
||||
exchange.SetDirection("buy")
|
||||
exchange.Buy(-1, position[0].Amount)
|
||||
}
|
||||
}
|
||||
if (position[0].Type == 1) {
|
||||
if (position[0].Profit > profit) {
|
||||
exchange.SetDirection("closesell")
|
||||
exchange.Buy(-1, position[0].Amount)
|
||||
}
|
||||
if (position[0].Profit < position[0].Margin * -1) {
|
||||
exchange.SetDirection("sell")
|
||||
exchange.Sell(-1, position[0].Amount)
|
||||
}
|
||||
}
|
||||
Sleep(60000)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
> 策略出处
|
||||
|
||||
https://www.fmz.com/strategy/270689
|
||||
|
||||
> 更新时间
|
||||
|
||||
2022-04-24 23:05:35
|
||||
Reference in New Issue
Block a user