Advertisement
gpearson100

Untitled

Jun 1st, 2017
265
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. I am NOT responsible for your losses if any occur.
  26. ###
  27.  
  28. ### CREDITS
  29. The VIX and Swing indicators used here were originally by Chris Moody at TradingView.
  30. Trading logic is my own.
  31. Thanks to all at Cryptotrader.org that helped me along the way.
  32. ###
  33.  
  34. ### ADVICE
  35. Rather than just trading with this, perhaps make this bot your own. Use it as a learning tool. Edit it to trade as you like to match your strategy.
  36. View this as a template for a long term trend trader with added scalping.
  37. Backtesting is your friend. Backtest over long periods to identify strengths and weaknesses.
  38. ###
  39.  
  40.  
  41. ############
  42. ### CODE ###
  43. ############
  44.  
  45. STOP_LOSS = askParam 'Use a Stop Loss?', false
  46. STOP_LOSS_PERCENTAGE = askParam 'If so, Stop Loss Percentage?', 5
  47. SCALP = askParam 'Use Scalping?', true
  48. SPLIT = askParam 'Split orders up?', false
  49. SPLIT_AMOUNT = askParam 'If so, split into how many?', 4
  50. PERIOD = askParam 'Trend reaction time (Max = 250 | Min = 50 | Default = 250 )', 250
  51. SNIPE = askParam 'Use Fat Finger Sniping?', false
  52. CODE = askParam 'Code to remove donation requests', 0
  53.  
  54. class VIX
  55.     constructor: (@period) ->
  56.         @close = []
  57.         @wvf = []
  58.         @trade = []
  59.         @count = 0
  60.  
  61.         # INITIALIZE ARRAYS
  62.         for [@close.length..22]
  63.             @close.push 0
  64.         for [@wvf.length..@period]
  65.             @wvf.push 0
  66.         for [@trade.length..10]
  67.             @trade.push 0
  68.        
  69.     calculate: (instrument) ->
  70.  
  71.         close = instrument.close[instrument.close.length-1]
  72.         high = instrument.high[instrument.high.length-1]
  73.         low = instrument.low[instrument.low.length-1]
  74.        
  75.  
  76.         # INCREASE DATA COUNT
  77.         @count++
  78.        
  79.         # REMOVE OLD DATA
  80.         @close.pop()
  81.         @wvf.pop()
  82.         @trade.pop()
  83.  
  84.         # ADD NEW DATA
  85.         @close.unshift(0)
  86.         @wvf.unshift(0)
  87.         @trade.unshift(0)
  88.  
  89.         # CALCULATE
  90.         @close[0] = close
  91.        
  92.         highest = (@close.reduce (a,b) -> Math.max a, b)
  93.  
  94.         @wvf[0] = ((highest - low) / (highest)) * 100
  95.  
  96.         sdev = talib.STDDEV
  97.             inReal: @wvf
  98.             startIdx: 0
  99.             endIdx: @wvf.length-1
  100.             optInTimePeriod: @period
  101.             optInNbDev: 1
  102.         sdev = sdev[sdev.length-1]
  103.  
  104.         midline = talib.SMA
  105.             inReal: @wvf
  106.             startIdx: 0
  107.             endIdx: @wvf.length-1
  108.             optInTimePeriod: @period
  109.         midline = midline[midline.length-1]
  110.  
  111.         lowerband = midline - sdev
  112.         upperband = midline + sdev
  113.  
  114.         rangehigh = (@wvf.reduce (a,b) -> Math.max a, b) * 0.85
  115.         rangelow = (@wvf.reduce (a,b) -> Math.min a, b) * 1.01
  116.  
  117.         if @wvf[0] >= upperband or @wvf[0] >= rangehigh
  118.             @trade[0] = 0
  119.             plotMark
  120.                 "wvf1": @wvf[0]
  121.         else
  122.             @trade[0] = 1
  123.             plotMark
  124.                 "wvf2": @wvf[0]
  125.            
  126.  
  127.         # RETURN DATA
  128.         result =
  129.             wvf: @wvf[0]
  130.             rangehigh: rangehigh
  131.             rangelow: rangelow
  132.             trade: @trade
  133.  
  134.         return result
  135.  
  136. class GANNSWING
  137.     constructor: (@period) ->
  138.         @count = 0
  139.         @buycount = 0
  140.         @sellcount = 0
  141.         @lowma = []
  142.         @highma = []
  143.         @fastlowma = []
  144.         @fasthighma = []
  145.  
  146.         # INITIALIZE ARRAYS
  147.         for [@lowma.length..5]
  148.             @lowma.push 0
  149.         for [@highma.length..5]
  150.             @highma.push 0
  151.         for [@fastlowma.length..5]
  152.             @fastlowma.push 0
  153.         for [@fasthighma.length..5]
  154.             @fasthighma.push 0
  155.        
  156.     calculate: (instrument) ->        
  157.  
  158.         close = instrument.close[instrument.close.length-1]
  159.         high = instrument.high[instrument.high.length-1]
  160.         low = instrument.low[instrument.low.length-1]
  161.  
  162.         # REMOVE OLD DATA
  163.         @lowma.pop()
  164.         @highma.pop()
  165.         @fastlowma.pop()
  166.         @fasthighma.pop()
  167.  
  168.         # ADD NEW DATA
  169.         @lowma.unshift(0)
  170.         @highma.unshift(0)
  171.         @fastlowma.unshift(0)
  172.         @fasthighma.unshift(0)
  173.  
  174.  
  175.         # CALCULATE
  176.         highma = talib.SMA
  177.             inReal: instrument.high
  178.             startIdx: 0
  179.             endIdx: instrument.high.length-1
  180.             optInTimePeriod: @period
  181.         @highma[0] = highma[highma.length-1]
  182.  
  183.         lowma = talib.SMA
  184.             inReal: instrument.low
  185.             startIdx: 0
  186.             endIdx: instrument.low.length-1
  187.             optInTimePeriod: @period
  188.         @lowma[0] = lowma[lowma.length-1]
  189.  
  190.         fasthighma = talib.SMA
  191.             inReal: instrument.high
  192.             startIdx: 0
  193.             endIdx: instrument.high.length-1
  194.             optInTimePeriod: @period / 5
  195.         @fasthighma[0] = fasthighma[fasthighma.length-1]
  196.  
  197.         fastlowma = talib.SMA
  198.             inReal: instrument.low
  199.             startIdx: 0
  200.             endIdx: instrument.low.length-1
  201.             optInTimePeriod: @period / 5
  202.         @fastlowma[0] = fastlowma[fastlowma.length-1]
  203.  
  204.        
  205.         if close > @highma[1] * 0.998 or (close > @fasthighma[1] and close > @fastlowma[1] * 1.01 and @fasthighma[1] > @highma[1])
  206.             hld = 1
  207.         else if close < @lowma[1] / 0.998 or (close < @fastlowma[1] and close < @fasthighma[1] / 1.01 and @fastlowma[1] < @lowma[1])
  208.             hld = -1
  209.         else
  210.             hld = 0
  211.  
  212.         if hld != 0
  213.             @count++
  214.  
  215.         if hld != 0 && @count == 1
  216.             hlv = hld
  217.             @count = 0
  218.         else
  219.             hlv = 0
  220.  
  221.         if hlv == -1
  222.             hi = @highma[0]
  223.             plotMark
  224.                 "hi": 50
  225.             @sellcount++
  226.             @buycount = 0
  227.  
  228.         if hlv == 1
  229.             lo = @lowma[0]
  230.             plotMark
  231.                 "lo": -5
  232.             @buycount++
  233.             @sellcount = 0
  234.  
  235.         if @buycount == 3
  236.             tradebuy = true
  237.             @buycount = 0
  238.         else
  239.             tradebuy = false
  240.  
  241.  
  242.         if @sellcount == 3
  243.             tradesell = true
  244.             @sellcount = 0
  245.         else
  246.             tradesell = false
  247.    
  248.  
  249.         # RETURN DATA
  250.         result =
  251.             tradesell: tradesell
  252.             tradebuy: tradebuy
  253.  
  254.         return result
  255.  
  256. class FUNCTIONS
  257.    
  258.     @ROUND_DOWN: (value, places) ->
  259.         offset = Math.pow(10, places)
  260.         return Math.floor(value*offset)/offset
  261.        
  262. class TRADE    
  263.    
  264.     @BUY: (instrument, amount, split, timeout) ->
  265.         price = instrument.price * 1.005
  266.  
  267.         if split > 0
  268.             amount = FUNCTIONS.ROUND_DOWN((portfolio.positions[instrument.curr()].amount/split)/price, 8)
  269.             for [0..split]
  270.                 buy(instrument, amount, price, timeout)
  271.         else
  272.             buy(instrument, null, price, timeout)
  273.        
  274.     @SELL: (instrument, amount, split, timeout) ->
  275.         price = instrument.price * 0.995
  276.  
  277.         if split > 0
  278.             amount = FUNCTIONS.ROUND_DOWN(portfolio.positions[instrument.asset()].amount/split, 8)
  279.             for [0..split]
  280.                 sell(instrument, amount, price, timeout)
  281.         else
  282.             sell(instrument, amount, price, timeout)      
  283.  
  284. init: (context)->
  285.    
  286.     context.vix     = new VIX(20)               # Period of stddev and midline
  287.     context.swing   = new GANNSWING(PERIOD)       # Period of highma and lowma
  288.  
  289.     # FOR FINALISE STATS
  290.     context.balance_curr = 0
  291.     context.balance_btc = 0
  292.     context.price = 0
  293.  
  294.     # TRADING
  295.     if SPLIT
  296.         context.trade_split = SPLIT_AMOUNT
  297.     else
  298.         context.trade_split = 0
  299.     context.trade_timeout   = 3000  
  300.  
  301.  
  302.  
  303. handle: (context, data, storage)->
  304.  
  305.     instrument = data.instruments[0]
  306.     price = instrument.close[instrument.close.length - 1]
  307.     storage.lastBuyPrice ?= 0
  308.     storage.lastSellPrice ?= 0
  309.     storage.TICK ?= 0
  310.     storage.NAG ?= 1
  311.     storage.wintrades ?= 0
  312.     storage.losetrades ?= 0
  313.     storage.coolOff ?= 0
  314.     trading = 0
  315.  
  316.     # FOR FINALISE STATS
  317.     context.price = instrument.close[instrument.close.length - 1]
  318.     context.balance_curr = portfolio.positions[instrument.curr()].amount
  319.     context.balance_btc = portfolio.positions[instrument.asset()].amount
  320.  
  321.     # CALLING INDICATORS
  322.     vix = context.vix.calculate(instrument)
  323.     wvf = vix.wvf
  324.     rangehigh = vix.rangehigh
  325.     rangelow = vix.rangelow
  326.     trade = vix.trade
  327.  
  328.     swing = context.swing.calculate(instrument)
  329.     tradesell = swing.tradesell
  330.     tradebuy = swing.tradebuy
  331.  
  332.     # LOGGING
  333.  
  334.     today = new Date
  335.     day = today.getDate()
  336.     month = today.getMonth()
  337.     combo = day + month + 1
  338.  
  339.     if storage.TICK == 0
  340.         storage.balance_curr_start = portfolio.positions[instrument.curr()].amount
  341.         storage.balance_btc_start = portfolio.positions[instrument.asset()].amount
  342.         storage.price_start = price
  343.         if combo == CODE
  344.             storage.NAG = 0
  345.          # WELCOME
  346.         info "###"
  347.         info "Welcome to the Trendatron 5000 Donation Bot."    
  348.         if storage.NAG == 1
  349.             info "Thanks for choosing this free bot. As many hours have gone into its creation, please consider a donation to:"
  350.             info "BTC: 1GGZU5mAUSLxVDegdxjakTLqZy7zizRH74"
  351.             info "(The bot carries on regardless of donations - don't worry.)"
  352.             info "If you have donated PM me for a code to make donation requests disappear."
  353.         else
  354.             info "Thanks for choosing to donate. Appreciated."
  355.         if STOP_LOSS == true
  356.             info "You chose to use a Stop Loss, with a cutoff of " + STOP_LOSS_PERCENTAGE + " percent."
  357.         if SCALP == true
  358.             info "You chose to use scalping (default bot behaviour)"
  359.         if SPLIT == true
  360.             info "You chose to split orders up into " + SPLIT_AMOUNT + " orders."
  361.         if SNIPE == true
  362.             info "You chose to enable sniping."
  363.         info "###"
  364.  
  365.  
  366.     starting_btc_equiv = storage.balance_btc_start + storage.balance_curr_start / storage.price_start
  367.     current_btc_equiv = context.balance_btc + context.balance_curr / price
  368.     starting_fiat_equiv = storage.balance_curr_start + storage.balance_btc_start * storage.price_start
  369.     current_fiat_equiv = context.balance_curr + context.balance_btc * price
  370.     efficiency = Math.round((current_btc_equiv / starting_btc_equiv) * 1000) / 1000
  371.     efficiency_percent = Math.round((((current_btc_equiv / starting_btc_equiv) - 1) * 100) * 10) / 10
  372.     market_efficiency = Math.round((((context.price / storage.price_start) - 1) * 100) * 10) / 10
  373.     bot_efficiency = Math.round((((current_fiat_equiv / starting_fiat_equiv) - 1) * 100) * 10) / 10
  374.     pairs = instrument.id.toUpperCase().split '_'
  375.     pair1 = pairs[0]    
  376.     pair2 = pairs[1]
  377.  
  378.     storage.TICK++
  379.    
  380.     if Math.round(storage.TICK/24) == (storage.TICK/24)
  381.         warn " "
  382.         info "================= Day " + Math.round(storage.TICK/24) + " Log ==================="
  383.         debug "Current " + pair2 + ": " + Math.round(context.balance_curr*100)/100 + " | Current " + pair1 + ": " +  Math.round(context.balance_btc*100)/100
  384.         debug "Starting " + pair2 + ": " + Math.round(storage.balance_curr_start*100)/100 + " | Starting " + pair1 + ": " +  Math.round(storage.balance_btc_start*100)/100
  385.         debug "Current Portfolio Worth: " + Math.round(((context.balance_btc * price) + context.balance_curr)*100)/100
  386.         debug "Starting Portfolio Worth: " + Math.round(((storage.balance_btc_start * storage.price_start) + storage.balance_curr_start)*100)/100
  387.         debug "Trades: Won = " + storage.wintrades + " | Lost = " + storage.losetrades + " | Total = " + (storage.wintrades + storage.losetrades) + " | W/L = " + (Math.round(((storage.wintrades / (storage.wintrades + storage.losetrades) * 100))*100)/100) + "%"
  388.         debug "Efficiency of Buy and Hold: " + market_efficiency + "%"
  389.         debug "Efficiency of Bot: " + bot_efficiency + "%"
  390.         debug "Efficiency of Bot Vs Buy and Hold: " + efficiency + " which equals " + efficiency_percent + "%"
  391.         info "==============================================="
  392.         warn " "
  393.  
  394.     if Math.round(storage.TICK/24) == (storage.TICK/24) && storage.NAG == 1
  395.         info "###"
  396.         info "Thanks for using this bot. Please consider a donation to:"
  397.         info "BTC: 1GGZU5mAUSLxVDegdxjakTLqZy7zizRH74"
  398.         info "(The bot carries on regardless of donations - don't worry.)"
  399.         info "If you have donated PM me for a code to make donation requests disappear."
  400.         info "###"
  401.    
  402.  
  403.     # TRADING
  404.     if context.balance_curr/price > 0.01
  405.         if tradebuy == true && storage.coolOff <= 0
  406.             if TRADE.BUY(instrument, null, context.trade_split, context.trade_timeout)
  407.                 storage.lastBuyPrice = price
  408.                 storage.stop = true
  409.                 info "#########"
  410.                 info "Trend Buy"
  411.                 info "#########"
  412.                 trading = 1
  413.                 sendEmail "Trendatron TREND BUY" + " - Current Fiat: " + Math.round(context.balance_curr*100)/100 + " | Current BTC: " +  Math.round(context.balance_btc*100)/100
  414.  
  415.     if context.balance_curr/price > 0.01 && SCALP == true && storage.coolOff <= 0
  416.         if trade[0] == 1 && trade[1] == 1 && trade[2] == 0 && trade[3] == 0 && trade[4] == 0 && trade[5] == 0 && wvf > 8.5
  417.             if TRADE.BUY(instrument, null, context.trade_split, context.trade_timeout)
  418.                 storage.lastBuyPrice = price
  419.                 storage.stop = true
  420.                 info "#########"
  421.                 info "Scalp Buy"
  422.                 info "#########"
  423.                 trading = 1
  424.                 sendEmail "Trendatron SCALP BUY" + " - Current Fiat: " + Math.round(context.balance_curr*100)/100 + " | Current BTC: " +  Math.round(context.balance_btc*100)/100
  425.  
  426.     if context.balance_btc > 0.01
  427.         if (tradesell == true && wvf < 2.85) or (tradebuy == true && wvf > 8.5 && trade[0] == 1 && trade[1] == 0)
  428.             if TRADE.SELL(instrument, null, context.trade_split, context.trade_timeout)
  429.                 storage.lastSellPrice = price
  430.                 storage.stop = false
  431.                 warn "##########"
  432.                 warn "Trend Sell"
  433.                 warn "##########"
  434.                 trading = 1
  435.                 if storage.lastSellPrice > storage.lastBuyPrice
  436.                     storage.wintrades++
  437.                 else
  438.                     storage.losetrades++
  439.                 sendEmail "Trendatron TREND SELL" + " - Current Fiat: " + Math.round(context.balance_curr*100)/100 + " | Current BTC: " +  Math.round(context.balance_btc*100)/100
  440.    
  441.     if STOP_LOSS
  442.         if storage.stop == true && price < storage.lastBuyPrice * (1 - (STOP_LOSS_PERCENTAGE / 100))
  443.             if TRADE.SELL(instrument, null, context.trade_split, context.trade_timeout)
  444.                 storage.lastSellPrice = price
  445.                 storage.stop = false
  446.                 storage.coolOff = 30
  447.                 warn "##############"
  448.                 warn "Stop Loss Sell"
  449.                 warn "##############"
  450.                 trading = 1
  451.                 if storage.lastSellPrice > storage.lastBuyPrice
  452.                     storage.wintrades++
  453.                 else
  454.                     storage.losetrades++
  455.                 sendEmail "Trendatron STOP LOSS SELL" + " - Current Fiat: " + Math.round(context.balance_curr*100)/100 + " | Current BTC: " +  Math.round(context.balance_btc*100)/100
  456.  
  457.     if SNIPE && trading == 0
  458.         if context.balance_btc > 0.05
  459.             if sell instrument,null,instrument.price * 1.1,3000
  460.                 warn "##########"
  461.                 warn "Snipe Sell"
  462.                 warn "##########"
  463.         if context.balance_curr > 10
  464.             if buy instrument,null,instrument.price * 0.9,3000
  465.                 info "#########"
  466.                 info "Snipe Buy"
  467.                 info "#########"
  468.  
  469.     storage.coolOff--
  470.  
  471.     # PLOTTING / DEBUG
  472.     plot
  473.         wvf: wvf
  474.         rangehigh: rangehigh
  475.         rangelow: rangelow
  476.     setPlotOptions
  477.         wvf:
  478.             secondary: true
  479.         rangehigh:
  480.             secondary: true
  481.         rangelow:
  482.             secondary: true
  483.         wvf1:
  484.             secondary: true
  485.             color: 'blue'
  486.             size: 1
  487.         wvf2:
  488.             secondary: true
  489.             color: 'black'
  490.             size: 1
  491.         lo:
  492.             color: 'green'
  493.             secondary: true
  494.             size: 4
  495.         hi:
  496.             color: 'red'
  497.             secondary: true
  498.             size: 4
  499.  
  500.    
  501.  
  502.    
  503. finalize: (contex, data)->
  504.  
  505.     # DISPLAY FINALISE STATS
  506.     if context.balance_curr > 10
  507.         info "Final Equiv: " + Math.round(context.balance_curr/context.price*100)/100
  508.     if context.balance_btc > 0.05
  509.         info "Final Value: " + Math.round(context.balance_btc*100)/100
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement