Advertisement
zmnkh

Untitled

Oct 17th, 2017
2,266
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #######################
  2. ### TRENDATRON 5000 ###
  3. #######################
  4.  
  5. ### INTRO
  6. https://cryptotrader.org/strategies/peKY35zY2Z2G56rLi
  7. by aspiramedia (https://cryptotrader.org/aspiramedia)
  8.  
  9. Please PM me with any updates, feedback, bugs, suggestions, criticism etc.
  10. Please leave this header intact, adding your own comments in EDITOR'S COMMENTS.
  11. Edited bots are NOT for submission into the CryptoTrader.org Strategies section.
  12. ###
  13.  
  14. ### EDITOR'S COMMENTS
  15. Made any edits? Why not explain here.
  16. ###
  17.  
  18. ### DONATIONS
  19. I am releasing this as a donation based bot. I am releasing this in hope of obtaining some donations from users here.
  20. Please donate BTC to: 1GGZU5mAUSLxVDegdxjakTLqZy7zizRH74
  21. ###
  22.  
  23. ### DISCLAIMER
  24. As usual with all trading, only trade with what you are able to lose.
  25. Start small.
  26. I am NOT responsible for your losses if any occur.
  27. ###
  28.  
  29. ### CREDITS
  30. The VIX and Swing indicators used here were originally by Chris Moody at TradingView.
  31. Trading logic is my own.
  32. Thanks to all at Cryptotrader.org that helped me along the way.
  33. ###
  34.  
  35. ### ADVICE
  36. Rather than just trading with this, I strongly recommend making this bot your own.
  37. Use it as a learning tool.
  38. Edit it to trade as you like to match your strategy.
  39. View this as a template for a long term trend trader with added scalping.
  40. Backtesting is your friend. Backtest over long periods to identify strengths and weaknesses.
  41. ###
  42.  
  43.  
  44. ############
  45. ### CODE ###
  46. ############
  47.  
  48. STOP_LOSS = askParam 'Use a Stop Loss?', false
  49. STOP_LOSS_PERCENTAGE = askParam 'If so, Stop Loss Percentage?', 5
  50. SCALP = askParam 'Use Scalping?', true
  51. SPLIT = askParam 'Split orders up?', false
  52. SPLIT_AMOUNT = askParam 'If so, split into how many?', 4
  53. PERIOD = askParam 'Trend reaction time (Max = 250 | Min = 50 | Default = 250 )', 250
  54.  
  55. class VIX
  56.     constructor: (@period) ->
  57.         @close = []
  58.         @wvf = []
  59.         @trade = []
  60.         @count = 0
  61.  
  62.         # INITIALIZE ARRAYS
  63.         for [@close.length..22]
  64.             @close.push 0
  65.         for [@wvf.length..@period]
  66.             @wvf.push 0
  67.         for [@trade.length..10]
  68.             @trade.push 0
  69.        
  70.     calculate: (instrument) ->
  71.  
  72.         close = instrument.close[instrument.close.length-1]
  73.         high = instrument.high[instrument.high.length-1]
  74.         low = instrument.low[instrument.low.length-1]
  75.        
  76.  
  77.         # INCREASE DATA COUNT
  78.         @count++
  79.        
  80.         # REMOVE OLD DATA
  81.         @close.pop()
  82.         @wvf.pop()
  83.         @trade.pop()
  84.  
  85.         # ADD NEW DATA
  86.         @close.unshift(0)
  87.         @wvf.unshift(0)
  88.         @trade.unshift(0)
  89.  
  90.         # CALCULATE
  91.         @close[0] = close
  92.        
  93.         highest = (@close.reduce (a,b) -> Math.max a, b)
  94.  
  95.         @wvf[0] = ((highest - low) / (highest)) * 100
  96.  
  97.         sdev = talib.STDDEV
  98.             inReal: @wvf
  99.             startIdx: 0
  100.             endIdx: @wvf.length-1
  101.             optInTimePeriod: @period
  102.             optInNbDev: 1
  103.         sdev = sdev[sdev.length-1]
  104.  
  105.         midline = talib.SMA
  106.             inReal: @wvf
  107.             startIdx: 0
  108.             endIdx: @wvf.length-1
  109.             optInTimePeriod: @period
  110.         midline = midline[midline.length-1]
  111.  
  112.         lowerband = midline - sdev
  113.         upperband = midline + sdev
  114.  
  115.         rangehigh = (@wvf.reduce (a,b) -> Math.max a, b) * 0.85
  116.         rangelow = (@wvf.reduce (a,b) -> Math.min a, b) * 1.01
  117.  
  118.         if @wvf[0] >= upperband or @wvf[0] >= rangehigh
  119.             @trade[0] = 0
  120.             plotMark
  121.                 "wvf1": @wvf[0]
  122.         else
  123.             @trade[0] = 1
  124.             plotMark
  125.                 "wvf2": @wvf[0]
  126.            
  127.  
  128.         # RETURN DATA
  129.         result =
  130.             wvf: @wvf[0]
  131.             rangehigh: rangehigh
  132.             rangelow: rangelow
  133.             trade: @trade
  134.  
  135.         return result
  136.  
  137. class GANNSWING
  138.     constructor: (@period) ->
  139.         @count = 0
  140.         @buycount = 0
  141.         @sellcount = 0
  142.         @lowma = []
  143.         @highma = []
  144.  
  145.         # INITIALIZE ARRAYS
  146.         for [@lowma.length..5]
  147.             @lowma.push 0
  148.         for [@highma.length..5]
  149.             @highma.push 0
  150.        
  151.     calculate: (instrument) ->        
  152.  
  153.         close = instrument.close[instrument.close.length-1]
  154.         high = instrument.high[instrument.high.length-1]
  155.         low = instrument.low[instrument.low.length-1]
  156.  
  157.         # REMOVE OLD DATA
  158.         @lowma.pop()
  159.         @highma.pop()
  160.  
  161.         # ADD NEW DATA
  162.         @lowma.unshift(0)
  163.         @highma.unshift(0)
  164.  
  165.         # CALCULATE
  166.         highma = talib.SMA
  167.             inReal: instrument.high
  168.             startIdx: 0
  169.             endIdx: instrument.high.length-1
  170.             optInTimePeriod: @period
  171.         @highma[0] = highma[highma.length-1]
  172.  
  173.         lowma = talib.SMA
  174.             inReal: instrument.low
  175.             startIdx: 0
  176.             endIdx: instrument.low.length-1
  177.             optInTimePeriod: @period
  178.         @lowma[0] = lowma[lowma.length-1]
  179.  
  180.         if close > @highma[1]
  181.             hld = 1
  182.         else if close < @lowma[1]
  183.             hld = -1
  184.         else
  185.             hld = 0
  186.  
  187.         if hld != 0
  188.             @count++
  189.  
  190.         if hld != 0 && @count == 1
  191.             hlv = hld
  192.             @count = 0
  193.         else
  194.             hlv = 0
  195.  
  196.         if hlv == -1
  197.             hi = @highma[0]
  198.             plotMark
  199.                 "hi": hi * 1.01
  200.             @sellcount++
  201.             @buycount = 0
  202.  
  203.         if hlv == 1
  204.             lo = @lowma[0]
  205.             plotMark
  206.                 "lo": lo / 1.01
  207.             @buycount++
  208.             @sellcount = 0
  209.  
  210.         if @buycount == 3
  211.             tradebuy = true
  212.             @buycount = 0
  213.         else
  214.             tradebuy = false
  215.  
  216.  
  217.         if @sellcount == 3
  218.             tradesell = true
  219.             @sellcount = 0
  220.         else
  221.             tradesell = false
  222.    
  223.  
  224.         # RETURN DATA
  225.         result =
  226.             tradesell: tradesell
  227.             tradebuy: tradebuy
  228.  
  229.         return result
  230.  
  231. class FUNCTIONS
  232.    
  233.     @ROUND_DOWN: (value, places) ->
  234.         offset = Math.pow(10, places)
  235.         return Math.floor(value*offset)/offset
  236.        
  237. class TRADE    
  238.    
  239.     @BUY: (instrument, amount, split, timeout) ->
  240.         price = instrument.price * 1.01
  241.  
  242.         if split > 0
  243.             amount = FUNCTIONS.ROUND_DOWN((portfolio.positions[instrument.curr()].amount/split)/price, 8)
  244.             for [0..split]
  245.                 buy(instrument, amount, price, timeout)
  246.         else
  247.             buy(instrument, null, price, timeout)
  248.        
  249.     @SELL: (instrument, amount, split, timeout) ->
  250.         price = instrument.price * 0.99
  251.  
  252.         if split > 0
  253.             amount = FUNCTIONS.ROUND_DOWN(portfolio.positions[instrument.asset()].amount/split, 8)
  254.             for [0..split]
  255.                 sell(instrument, amount, price, timeout)
  256.         else
  257.             sell(instrument, amount, price, timeout)      
  258.  
  259. init: (context)->
  260.    
  261.     context.vix = new VIX(20)               # Period of stddev and midline
  262.     context.swing = new GANNSWING(PERIOD)   # Period of highma and lowma
  263.  
  264.     # FOR FINALISE STATS
  265.     context.balance_curr = 0
  266.     context.balance_btc = 0
  267.     context.price = 0
  268.  
  269.     # TRADING
  270.     if SPLIT
  271.         context.trade_split = SPLIT_AMOUNT
  272.     else
  273.         context.trade_split = 0
  274.     context.trade_timeout   = 3000
  275.  
  276.     # LOGGING
  277.     context.TICK = 0
  278.     context.balance_curr_start = 0
  279.     context.balance_btc_start = 0
  280.     context.price_start = 0
  281.  
  282.     # WELCOME
  283.     info "###"
  284.     info "Welcome to the Trendatron Bot."
  285.     info "Thanks for choosing this free bot. As many hours have gone into its creation, please consider a donation to:"
  286.     info "BTC: 1GGZU5mAUSLxVDegdxjakTLqZy7zizRH74"
  287.     info "(The bot carries on regardless of donations - don't worry. And if you have donated then thank you.)"
  288.     if STOP_LOSS == true
  289.         info "You chose to use a Stop Loss, with a cutoff of " + STOP_LOSS_PERCENTAGE + " percent."
  290.     if SCALP == true
  291.         info "You chose to use scalping (default bot behaviour)"
  292.     if SPLIT == true
  293.         info "You chose to split orders up into " + SPLIT_AMOUNT + " orders."
  294.  
  295.     info "###"
  296.  
  297.  
  298.  
  299.  
  300. handle: (context, data, storage)->
  301.  
  302.     instrument = data.instruments[0]
  303.     price = instrument.close[instrument.close.length - 1]
  304.     storage.lastBuyPrice ?= 0
  305.  
  306.     # FOR FINALISE STATS
  307.     context.price = instrument.close[instrument.close.length - 1]
  308.     context.balance_curr = portfolio.positions[instrument.curr()].amount
  309.     context.balance_btc = portfolio.positions[instrument.asset()].amount
  310.  
  311.     # CALLING INDICATORS
  312.     vix = context.vix.calculate(instrument)
  313.     wvf = vix.wvf
  314.     rangehigh = vix.rangehigh
  315.     rangelow = vix.rangelow
  316.     trade = vix.trade
  317.  
  318.     swing = context.swing.calculate(instrument)
  319.     tradesell = swing.tradesell
  320.     tradebuy = swing.tradebuy
  321.    
  322.  
  323.     # TRADING
  324.     if context.balance_curr/price > 0.01
  325.         if tradebuy == true
  326.             if TRADE.BUY(instrument, null, context.trade_split, context.trade_timeout)
  327.                 storage.lastBuyPrice = price
  328.                 storage.stop = true
  329.                 info "#########"
  330.                 info "Trend Buy"
  331.                 info "#########"
  332.  
  333.     if context.balance_curr/price > 0.01 && SCALP == true
  334.         if trade[0] == 1 && trade[1] == 1 && trade[2] == 0 && trade[3] == 0 && trade[4] == 0 && trade[5] == 0 && wvf > 8.5
  335.             if TRADE.BUY(instrument, null, context.trade_split, context.trade_timeout)
  336.                 storage.lastBuyPrice = price
  337.                 storage.stop = true
  338.                 info "#########"
  339.                 info "Scalp Buy"
  340.                 info "#########"
  341.  
  342.     if context.balance_btc > 0.01
  343.         if (tradesell == true && wvf < 2.85) or (tradebuy == true && wvf > 8.5 && trade[0] == 1 && trade[1] == 0)
  344.             if TRADE.SELL(instrument, null, context.trade_split, context.trade_timeout)
  345.                 storage.lastBuyPrice = 0
  346.                 storage.lastSellPrice = price
  347.                 storage.stop = false
  348.                 warn "##########"
  349.                 warn "Trend Sell"
  350.                 warn "##########"
  351.    
  352.     # STOP LOSS
  353.     if STOP_LOSS
  354.         if storage.stop == true && price < storage.lastBuyPrice * (1 - (STOP_LOSS_PERCENTAGE / 100))
  355.             if TRADE.SELL(instrument, null, context.trade_split, context.trade_timeout)
  356.                 storage.lastBuyPrice = 0
  357.                 storage.lastSellPrice = price
  358.                 storage.stop = false
  359.                 warn "##############"
  360.                 warn "Stop Loss Sell"
  361.                 warn "##############"
  362.  
  363.     # PLOTTING / DEBUG
  364.     plot
  365.         wvf: wvf
  366.         rangehigh: rangehigh
  367.         rangelow: rangelow
  368.         normaliser: 25
  369.     setPlotOptions
  370.         wvf:
  371.             secondary: true
  372.         rangehigh:
  373.             secondary: true
  374.         rangelow:
  375.             secondary: true
  376.         wvf1:
  377.             secondary: true
  378.             color: 'blue'
  379.         wvf2:
  380.             secondary: true
  381.             color: 'black'
  382.         lo:
  383.             color: 'green'
  384.         hi:
  385.             color: 'red'
  386.         normaliser:
  387.             secondary: true
  388.             color: '#fffdf6'
  389.  
  390.     # LOGGING
  391.  
  392.     if context.TICK == 0
  393.         context.balance_curr_start = portfolio.positions[instrument.curr()].amount
  394.         context.balance_btc_start = portfolio.positions[instrument.asset()].amount
  395.         context.price_start = price
  396.  
  397.     starting_btc_equiv = context.balance_btc_start + context.balance_curr_start / context.price_start
  398.     current_btc_equiv = context.balance_btc + context.balance_curr / price
  399.     efficiency = Math.round((current_btc_equiv / starting_btc_equiv) * 1000) / 1000
  400.     efficiency_percent = Math.round((((current_btc_equiv / starting_btc_equiv) - 1) * 100) * 100) / 100
  401.  
  402.  
  403.  
  404.     context.TICK++
  405.     if Math.round(context.TICK/24) == (context.TICK/24)
  406.         warn "### Day " + context.TICK/24 + " Log"
  407.         debug "Current Fiat: " + Math.round(context.balance_curr*100)/100 + " | Current BTC: " +  Math.round(context.balance_btc*100)/100
  408.         debug "Starting Fiat: " + Math.round(context.balance_curr_start*100)/100 + " | Starting BTC: " +  Math.round(context.balance_btc_start*100)/100
  409.         debug "Current Portfolio Worth: " + Math.round(((context.balance_btc * price) + context.balance_curr)*100)/100
  410.         debug "Starting Portfolio Worth: " + Math.round(((context.balance_btc_start * context.price_start) + context.balance_curr_start)*100)/100
  411.         debug "Efficiency Vs Buy and Hold: " + efficiency + " which equals " + efficiency_percent + "%"
  412.         warn "###"
  413.  
  414.     if Math.round(context.TICK/744) == (context.TICK/744)
  415.         info "###"
  416.         info "Thanks for using this free bot for the last month. Please consider a donation to:"
  417.         info "BTC: 1GGZU5mAUSLxVDegdxjakTLqZy7zizRH74"
  418.         info "(The bot carries on regardless of donations - don't worry. And if you have donated then thank you.)"
  419.         info "Or maybe fill in an anonymous survey?"
  420.         info "https://docs.google.com/forms/d/1sWjADH4lPvcIy1LJ-N3lz9Bc3dGVefGBCHbzLRFJ7MQ/viewform"
  421.         info "###"
  422.    
  423.  
  424.    
  425. finalize: (contex, data)->
  426.  
  427.     # DISPLAY FINALISE STATS
  428.     if context.balance_curr > 10
  429.         info "Final BTC Equiv: " + Math.round(context.balance_curr/context.price*100)/100
  430.     if context.balance_btc > 0.05
  431.         info "Final BTC Value: " + Math.round(context.balance_btc*100)/100
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement