This commit is contained in:
root
2023-02-07 22:05:02 +08:00
parent 9e5ffa14ef
commit a6c574f3e0
15 changed files with 1211 additions and 239 deletions
@@ -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
View File
@@ -0,0 +1,200 @@
> 策略名称
HFT高频订单流因子
> 策略作者
发明者量化
> 策略描述
一个入门级订单流高频alpha因子, 可以做为市商策略的最优买卖定价距离参考, 信号归一为[-1, 1], 趋向1表示买方市场,趋向-1则是卖方市场, 策略会实时绘制因子值与最后成交价
策略使用OKX与币安期货websocket接口接收计算, 下图是指标效果, 可以看出有一定的有效性, 公开给高频入门的量化爱好者
![IMG](https://www.fmz.com/upload/asset/a89668d3b0189c8902.png)
> 策略参数
|参数|默认值|描述|
|----|----|----|
|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
@@ -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
+12 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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线。
![IMG](https://www.fmz.com/upload/asset/a7be2f213a94a4dc6b8f.png)
![IMG](https://www.fmz.com/upload/asset/a898d4d1a12440ee8bc4.png)
![IMG](https://www.fmz.com/upload/asset/a87da3bf5541e8c910da.png)
![IMG](https://www.fmz.com/upload/asset/a875e44f3b9fbff5a691.png)
综上所述,将6种K线收盘关系与3种K线收盘比较相结合,总共产生18种K线强弱关系,将多头最强的K线编码为9将最弱的K线编码为-9,其余依次按强弱关系递进编码,结果如图
![IMG](https://www.fmz.com/upload/asset/a86de64549f7f9a0fc87.png)
欢迎合作交流,共同学习进步~
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
+58
View File
@@ -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
+64
View File
@@ -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
-106
View File
@@ -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