воскресенье, 27 мая 2018 г.

Свечной анализ

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])
# Import the backtrader platform
import backtrader as bt

import requests
import json
import time
import math
from datetime import datetime
import pandas as pd

import talib
price = 0
prof = 1

def trade_log(self, op) :
    global PRICE
    global profit
    global prof
    dt = self.datas[0].datetime.date(0)
    if op == 'buy':
        PRICE = self.dataclose[0]
        print(
             '%s, BUY  Покупка, Price: %.2f' %
             (dt.isoformat(), PRICE)
             )
    if op == 'sell':
         PRICE2 = self.dataclose[0]
         profit = PRICE2/PRICE-0.004
         prof = prof * profit
         print('%s, SELL Продажа, Price: %.2f, Cost: %.2f,  Profit: %.3f, Prof: %.3f' %
             (dt.isoformat(), PRICE2, PRICE, profit, prof))

def get_polonix() :
    time_depth = 500
    start_day = 500
    st_time=time.time()-start_day*24*60*60
    end_time=st_time+time_depth*60*60*24
    pair = 'USDT_BTC'

    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=1800" % (pair,st_time,end_time))
    resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=14400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=300" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=86400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=21600" % (pair,st_time,end_time))

    data=[]
    chart_data={}
    chart_data = json.loads(resource.text)
    for elems in chart_data:
        data.append(elems)

    df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    df['openinterest']=0
    df['date'] = pd.to_datetime(df['date'], unit='s')
    #df = df[(df['date'] > '2017-12-15') & (df['date'] <= '2018-2-1')]
    df = df[(df['date'] > '2018-2-1') & (df['date'] <= '2018-4-1')]
    #df = df[(df['date'] > '2017-9-1') & (df['date'] <= '2018-1-1')]
    #df = df[(df['date'] >= '2018-4-1')]
    df = df.set_index('date')
    #print(df)
    return df

def get_finam() :
    df = pd.read_csv('SBER_160101_180523.csv')
    df = df.rename(columns={'<DATE>':'Date','<OPEN>':'Open','<HIGH>':'High','<LOW>':'Low','<CLOSE>':'Close','<VOL>':'Volume'})
    df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
    df['Openinterest']=0
    df = df.drop('<TIME>',1)
    #df = df[(df['datetime'] > '2018-1-1') & (df['datetime'] <= '2018-2-1')]
    df = df[(df['Date'] >= '2017-6-1')]
    df = df.set_index('Date')
    return df

# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (('BBandsperiod', 20),)

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        #print('%s, %s' % (dt.isoformat(), txt))

    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close

        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.redline = None
        self.blueline = None

        # Add a BBand indicator
        self.bband = bt.indicators.BBands(self.datas[0], period=self.params.BBandsperiod)

        #bt.indicators.MACDHisto(self.datas[0])
        #rsi = bt.indicators.RSI(self.datas[0])

        self.t_macd = bt.talib.MACD(self.datas[0], fastperiod=12, slowperiod=26, signalperiod=9, plotname='MACD')
        self.CDLHARAMI = bt.talib.CDLHARAMI(self.datas[0].open, self.datas[0].high, self.datas[0].low,self.datas[0].close, plotname='CDLHARAMI')
        #self.CDLENGULFING = bt.talib.CDLENGULFING(self.datas[0].open, self.datas[0].high, self.datas[0].low,self.datas[0].close, plotname='CDLENGULFING')
        #self.CDLBELTHOLD = bt.talib.CDLBELTHOLD(self.datas[0].open, self.datas[0].high, self.datas[0].low,self.datas[0].close, plotname='CDLBELTHOLD')
       

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

            self.bar_executed = len(self)

        # Write down: no pending order
        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        #print(self.CDLHARAMI[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        if (
           self.CDLHARAMI[0] == 100
           #or self.CDLENGULFING[0] == 100
           #or self.CDLBELTHOLD[0] == 100
           and self.t_macd.macd[0] > 0
           and  self.t_macd.macdsignal[0] > 0
           and not self.position
           ):

            # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()
            print(self.CDLHARAMI[0])
            trade_log(self,'buy')

        if (
           (
           self.CDLHARAMI[0] == -100
           #or self.CDLENGULFING[0] == -100
           #or self.CDLBELTHOLD[0] == -100
           or self.t_macd.macd[0] < 0
           or  self.t_macd.macdsignal[0] < 0
           )
           and self.position
           ):
            # SELL, SELL, SELL!!! (with all possible default parameters)
            self.log('SELL CREATE, %.2f' % self.dataclose[0])
            self.blueline = False
            self.redline = False
            # Keep track of the created order to avoid a 2nd order
            self.order = self.sell()
            print(self.CDLHARAMI[0])
            trade_log(self,'sell')

if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    cerebro.addstrategy(TestStrategy)

    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    #modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    #atapath = os.path.join(modpath, 'TSLA-USD.csv')

    # Create a Data Feed
    #data = bt.feeds.GenericCSVData(
        #dataname=datapath,
        # Do not pass values before this date
        #fromdate=datetime.datetime(2008, 4, 4),
        # Do not pass values before this date
        #todate=datetime.datetime(2016, 12, 2),

     #nullvalue=0.0,

     #dtformat=('%m/%d/%Y'),

     #datetime=0,
     #high=2,
     #low=3,
     #open=1,
     #close=4,
     #volume=5,
     #openinterest=-1)



    df = get_polonix()
    #df = get_finam()
    data = bt.feeds.PandasData(dataname=df)

    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=5)

    # Set the commission
    cerebro.broker.setcommission(commission=0.002)

    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Plot the result
    cerebro.plot(style='candlestick')

Heikin Ashi Solution

Backtrader: Working with Heikin Ashi
import backtrader as bt
from datetime import datetime
import math
import argparse

import requests
import json
import time
import math
from datetime import datetime
import pandas as pd


def get_polonix() :
    time_depth = 500
    start_day = 500
    st_time=time.time()-start_day*24*60*60
    end_time=st_time+time_depth*60*60*24
    pair = 'USDT_BTC'   
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=1800" % (pair,st_time,end_time))   
    resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=14400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=300" % (pair,st_time,end_time))   
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=86400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=21600" % (pair,st_time,end_time))

    data=[]
    chart_data={}
    chart_data = json.loads(resource.text)
    for elems in chart_data:
        data.append(elems)

    df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    df['openinterest']=0
    df['date'] = pd.to_datetime(df['date'], unit='s')
    #df = df[(df['date'] > '2018-1-1') & (df['date'] <= '2018-2-1')]
    #df = df[(df['date'] > '2017-9-1') & (df['date'] <= '2018-1-1')]
    df = df[(df['date'] >= '2018-4-1')]
    df = df.set_index('date')
    #print(df)
    return df 


def parse_args():
    parser = argparse.ArgumentParser(description='Ngyuen: Price/Volume Anomaly Detection Strategy')
    parser.add_argument('--debug',
                            action ='store_true',
                            help=('Print Debugs'))

    return parser.parse_args()



class HeikinStrategy(bt.Strategy):
    params = (('debug', False),)

    def __init__(self):
        # Set some pointers / references
        for i, d in enumerate(self.datas):
            if d._name == 'Real':
                self.real = d
            elif d._name == 'Heikin':
                self.hk = d


    def next(self):
        pos = self.getposition(self.real).size
        if not pos:
            if self.hk.close[0] > self.hk.open[0]: # Green Heikin
                self.buy(self.real, size=100)
            elif self.hk.close[0] < self.hk.open[0]: #Red Heikin
                self.sell(self.real, size=100)
            else:
                pass # Closed neutral
        else:
            if pos > 0 and self.hk.close[0] < self.hk.open[0]: # Red Heikin
                self.sell(self.real, size=200) # Reverse Position
            elif pos < 0 and self.hk.close[0] > self.hk.open[0]: # Green Heikin
                self.buy(self.real, size=200) # Reverse Position
            else:
                pass

        if self.p.debug:
            print('---------------------------- NEXT ----------------------------------')
            print("1: Data Name:                            {}".format(data._name))
            print("2: Bar Num:                              {}".format(len(data)))
            print("3: Current date:                         {}".format(data.datetime.datetime()))
            print('4: Open:                                 {}'.format(data.open[0]))
            print('5: High:                                 {}'.format(data.high[0]))
            print('6: Low:                                  {}'.format(data.low[0]))
            print('7: Close:                                {}'.format(data.close[0]))
            print('8: Volume:                               {}'.format(data.volume[0]))
            print('--------------------------------------------------------------------')


    def notify_trade(self,trade):

        if trade.isclosed:
            dt = self.data.datetime.date()
            print('---------------------------- TRADE ---------------------------------')
            print("1: Data Name:                            {}".format(trade.data._name))
            print("2: Bar Num:                              {}".format(len(trade.data)))
            print("3: Current date:                         {}".format(dt))
            print('4: Status:                               Trade Complete')
            print('5: Ref:                                  {}'.format(trade.ref))
            print('6: PnL:                                  {}'.format(round(trade.pnl,2)))
            print('--------------------------------------------------------------------')



args = parse_args()
#Variable for our starting cash
startcash = 1000000

#Create an instance of cerebro
cerebro = bt.Cerebro()


#Add our strategy
cerebro.addstrategy(HeikinStrategy, debug=args.debug)

df = get_polonix()
data = bt.feeds.PandasData(dataname=df)
dataHK = bt.feeds.PandasData(dataname=df)

#data = bt.feeds.Quandl(
    #dataname='F',
    #fromdate = datetime(2016,1,1),
    #todate = datetime(2017,1,1),
    #buffered= True
    #)

#dataHK = bt.feeds.Quandl(
    #dataname='F',
    #fromdate = datetime(2016,1,1),
    #todate = datetime(2017,1,1),
    #buffered= True
    #)


#Add the filter

dataHK.addfilter(bt.filters.HeikinAshi(dataHK))

#Add the data to Cerebro

cerebro.adddata(data, name="Real")
cerebro.adddata(dataHK, name="Heikin")

# Set our desired cash start
cerebro.broker.setcash(startcash)

# Run over everything
cerebro.run()


#Get final portfolio Value
portvalue = cerebro.broker.getvalue()
pnl = portvalue - startcash

#Print out the final result
print('Final Portfolio Value: ${}'.format(round(portvalue,2)))
print('P/L: ${}'.format(round(pnl,2)))


#Finally plot the end results
cerebro.plot(style='candlestick')

Backtrader finam стратегия болинджер добовляем ZigZag


взято здесь
Backtrader finam стратегия болинджер

class ZigZag(bt.ind.PeriodN):
    '''
      Identifies Peaks/Troughs of a timeseries
    '''
    lines = (
        'trend', 'last_pivot_t', 'last_pivot_x', 'last_pivot_ago',
        'zigzag_peak', 'zigzag_valley', 'zigzag', 'last_zigzag',
    )

    # Fancy plotting name
    # plotlines = dict(logreturn=dict(_name='log_ret'))
    plotinfo = dict(
        subplot=False,
        plotlinelabels=True, plotlinevalues=True, plotvaluetags=True,
    )

    plotlines = dict(
        trend=dict(marker='', markersize=0.0, ls='', _plotskip=True),
        last_pivot_t=dict(marker='', markersize=0.0, ls='', _plotskip=True),
        last_pivot_x=dict(marker='', markersize=0.0, ls='', _plotskip=True),
        last_pivot_ago=dict(marker='', markersize=0.0, ls='', _plotskip=True),
        zigzag_peak=dict(marker='v', markersize=4.0, color='red',
                         fillstyle='full', ls=''),
        zigzag_valley=dict(marker='^', markersize=4.0, color='red',
                           fillstyle='full', ls=''),
        zigzag=dict(_name='zigzag', color='blue', ls='-', _skipnan=True),
        last_zigzag=dict(_name='last_zigzag', color='blue', ls='--', _skipnan=True),
    )

    # update value to standard for Moving Averages
    params = (
        ('period', 2),
        ('up_retrace', 0.1),
        ('dn_retrace', 0.1),
        ('bardist', 0.015),  # distance to max/min in absolute perc
    )

    def __init__(self):
        super(ZigZag, self).__init__()

        if not self.p.up_retrace:
            raise ValueError('Upward retracement should not be zero.')

        if not self.p.dn_retrace:
            raise ValueError('Downward retracement should not be zero.')

        if self.p.up_retrace < 0:
            self.p.up_retrace = -self.p.up_retrace

        if self.p.dn_retrace > 0:
            self.p.dn_retrace = -self.p.dn_retrace

        self.p.up_retrace = self.p.up_retrace / 100
        self.p.dn_retrace = self.p.dn_retrace / 100

        self.missing_val = float('nan')

    def prenext(self):
        self.lines.trend[0] = 0
        self.lines.last_pivot_t[0] = 0
        self.lines.last_pivot_x[0] = self.data[0]
        self.lines.last_pivot_ago[0] = 0
        self.lines.zigzag_peak[0] = self.missing_val
        self.lines.zigzag_valley[0] = self.missing_val
        self.lines.zigzag[0] = self.missing_val
        self.lines.last_zigzag[0] = self.missing_val

    def next(self):
        data = self.data
        trend = self.lines.trend
        last_pivot_t = self.lines.last_pivot_t
        last_pivot_x = self.lines.last_pivot_x
        last_pivot_ago = self.lines.last_pivot_ago
        zigzag_peak = self.lines.zigzag_peak
        zigzag_valley = self.lines.zigzag_valley
        zigzag = self.lines.zigzag
        last_zigzag = self.lines.last_zigzag

        x = data[0]
        r = x / last_pivot_x[-1] - 1
        curr_idx = len(data) - 1

        trend[0] = trend[-1]
        last_pivot_x[0] = last_pivot_x[-1]
        last_pivot_t[0] = last_pivot_t[-1]
        last_pivot_ago[0] = curr_idx - last_pivot_t[0]
        zigzag_peak[0] = self.missing_val
        zigzag_valley[0] = self.missing_val
        zigzag[0] = self.missing_val
        last_zigzag[0] = x

        if trend[-1] == 0:
            if r >= self.p.up_retrace:
                piv = last_pivot_x[0] * (1 - self.p.bardist)
                zigzag_valley[-int(last_pivot_ago[0])] = piv
                zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0]
                trend[0] = 1
                last_pivot_x[0] = x
                last_pivot_t[0] = curr_idx
            elif r <= self.p.dn_retrace:
                piv = last_pivot_x[0] * (1 + self.p.bardist)
                zigzag_peak[-int(last_pivot_ago[0])] = piv
                zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0]
                trend[0] = -1
                last_pivot_x[0] = x
                last_pivot_t[0] = curr_idx
        elif trend[-1] == -1:
            if r >= self.p.up_retrace:
                piv = last_pivot_x[0] * (1 - self.p.bardist)
                zigzag_valley[-int(last_pivot_ago[0])] = piv
                zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0]
                trend[0] = 1
                last_pivot_x[0] = x
                last_pivot_t[0] = curr_idx
            elif x < last_pivot_x[-1]:
                last_pivot_x[0] = x
                last_pivot_t[0] = curr_idx
        elif trend[-1] == 1:
            if r <= self.p.dn_retrace:
                piv = last_pivot_x[0] * (1 + self.p.bardist)
                zigzag_peak[-int(last_pivot_ago[0])] = piv
                zigzag[-int(last_pivot_ago[0])] = last_pivot_x[0]
                trend[0] = -1
                last_pivot_x[0] = x
                last_pivot_t[0] = curr_idx
            elif x > last_pivot_x[-1]:
                last_pivot_t[0] = curr_idx
                last_pivot_x[0] = x

        idx = 1
        while idx < len(self.zigzag) and math.isnan(zigzag[-idx]):
            last_zigzag[-idx] = self.missing_val
            idx += 1

        if idx < len(self.data):
            last_zigzag[-idx] = zigzag[-idx]

 ######################################################################
 Добавить в класс стратегии:
    def __init__(self):
        ........
        ........
        self.zigzag = ZigZag(self.datas[0], up_retrace=5, dn_retrace=-5, plot=True)

Backtrader finam стратегия болинджер

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt



import requests
import json
import time
import math
from datetime import datetime
import pandas as pd

import talib




price = 0
prof = 1


def trade_log(self, op) :
    global PRICE
    global profit
    global prof
    dt = self.datas[0].datetime.date(0)
    if op == 'buy':
        PRICE = self.dataclose[0]
        print(
             '%s, BUY  Покупка, Price: %.2f' %
             (dt.isoformat(), PRICE)
             )
    if op == 'sell':
         PRICE2 = self.dataclose[0]
         profit = PRICE2/PRICE-0.004
         prof = prof * profit
         print('%s, SELL Продажа, Price: %.2f, Cost: %.2f,  Profit: %.3f, Prof: %.3f' %
             (dt.isoformat(), PRICE2, PRICE, profit, prof))

def get_polonix() :
    time_depth = 500
    start_day = 500
    st_time=time.time()-start_day*24*60*60
    end_time=st_time+time_depth*60*60*24
    pair = 'USDT_BTC'

    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=1800" % (pair,st_time,end_time))
    resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=14400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=300" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=86400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=21600" % (pair,st_time,end_time))

    data=[]
    chart_data={}
    chart_data = json.loads(resource.text)
    for elems in chart_data:
        data.append(elems)

    df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    df['openinterest']=0
    df['date'] = pd.to_datetime(df['date'], unit='s')
    #df = df[(df['date'] > '2018-1-1') & (df['date'] <= '2018-2-1')]
    #df = df[(df['date'] > '2017-9-1') & (df['date'] <= '2018-1-1')]
    df = df[(df['date'] >= '2018-4-1')]
    df = df.set_index('date')
    #print(df)
    return df

def get_finam() :
    df = pd.read_csv('SBER_160101_180523.csv')
    df = df.rename(columns={'<DATE>':'Date','<OPEN>':'Open','<HIGH>':'High','<LOW>':'Low','<CLOSE>':'Close','<VOL>':'Volume'})
    df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d')
    df['Openinterest']=0
    df = df.drop('<TIME>',1)
    #df = df[(df['datetime'] > '2018-1-1') & (df['datetime'] <= '2018-2-1')]
    df = df[(df['Date'] >= '2017-6-1')]
    df = df.set_index('Date')
    return df

# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (('BBandsperiod', 20),)

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        #print('%s, %s' % (dt.isoformat(), txt))

    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close

        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.redline = None
        self.blueline = None

        # Add a BBand indicator
        self.bband = bt.indicators.BBands(self.datas[0], period=self.params.BBandsperiod)

        #bt.indicators.MACDHisto(self.datas[0])
        #rsi = bt.indicators.RSI(self.datas[0])

        self.t_macd = bt.talib.MACD(self.datas[0], fastperiod=12, slowperiod=26, signalperiod=9, plotname='MACD')

    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

            self.bar_executed = len(self)

        # Write down: no pending order
        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))

   

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        if (
           self.dataclose > self.bband.lines.mid
           and self.bband.lines.mid[0] > self.bband.lines.mid[-1]*1.001
           and self.t_macd.macd[0] > 0
           and  self.t_macd.macdsignal[0] > 0
           and not self.position
           ):

            # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()

            trade_log(self,'buy')

        if self.dataclose < self.bband.lines.mid and self.position:
            # SELL, SELL, SELL!!! (with all possible default parameters)
            self.log('SELL CREATE, %.2f' % self.dataclose[0])
            self.blueline = False
            self.redline = False
            # Keep track of the created order to avoid a 2nd order
            self.order = self.sell()
            trade_log(self,'sell')

if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    cerebro.addstrategy(TestStrategy)

    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    #modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    #atapath = os.path.join(modpath, 'TSLA-USD.csv')

    # Create a Data Feed
    #data = bt.feeds.GenericCSVData(
        #dataname=datapath,
        # Do not pass values before this date
        #fromdate=datetime.datetime(2008, 4, 4),
        # Do not pass values before this date
        #todate=datetime.datetime(2016, 12, 2),

     #nullvalue=0.0,

     #dtformat=('%m/%d/%Y'),

     #datetime=0,
     #high=2,
     #low=3,
     #open=1,
     #close=4,
     #volume=5,
     #openinterest=-1)



    #df = get_polonix()
    df = get_finam()
    data = bt.feeds.PandasData(dataname=df)

    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=5)

    # Set the commission
    cerebro.broker.setcommission(commission=0.002)

    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Plot the result
    cerebro.plot(style='candlestick')

суббота, 26 мая 2018 г.

Backtrader изспользуем talib

MACD Settings backtrader
Описание
TA-Lib Indicator Reference
Indicator Reference

Основа

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt
 
import requests
import json
import time
import math
from datetime import datetime
import pandas as pd 
import talib
 
 
price = 0
prof = 1


def trade_log(self, op) :
    global PRICE
    global profit
    global prof
    dt = self.datas[0].datetime.date(0)
    if op == 'buy':
        PRICE = self.dataclose[0]
        print(
             '%s, BUY  Покупка, Price: %.2f' %
             (dt.isoformat(), PRICE)
             )
    if op == 'sell':
         PRICE2 = self.dataclose[0]
         profit = PRICE2/PRICE-0.004
         prof = prof * profit
         print('%s, SELL Продажа, Price: %.2f, Cost: %.2f,  Profit: %.3f, Prof: %.3f' %
             (dt.isoformat(), PRICE2, PRICE, profit, prof)) 
 
def get_polonix() :
    time_depth = 500
    start_day = 500
    st_time=time.time()-start_day*24*60*60
    end_time=st_time+time_depth*60*60*24
    pair = 'USDT_BTC'

    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=1800" % (pair,st_time,end_time))
    resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=14400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=300" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=86400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=21600" % (pair,st_time,end_time))

    data=[]
    chart_data={}
    chart_data = json.loads(resource.text)
    for elems in chart_data:
        data.append(elems)

    df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    df['openinterest']=0
    df['date'] = pd.to_datetime(df['date'], unit='s')
    #df = df[(df['date'] > '2018-1-1') & (df['date'] <= '2018-2-1')]
    #df = df[(df['date'] > '2017-9-1') & (df['date'] <= '2018-1-1')]
    df = df[(df['date'] >= '2018-4-1')]
    df = df.set_index('date')
    #print(df)
    return df 
 
# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (('BBandsperiod', 20),)

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        #print('%s, %s' % (dt.isoformat(), txt))

    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close

        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.redline = None
        self.blueline = None

        # Add a BBand indicator
        self.bband = bt.indicators.BBands(self.datas[0], period=self.params.BBandsperiod)
        #bt.indicators.MACDHisto(self.datas[0])
        #rsi = bt.indicators.RSI(self.datas[0])
        self.t_macd = bt.talib.MACD(self.datas[0], fastperiod=12, slowperiod=26, signalperiod=9, plotname='MACD') 
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

            self.bar_executed = len(self)

        # Write down: no pending order
        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))

    

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        if self.dataclose < self.bband.lines.bot and not self.position:
         self.redline = True

        if self.dataclose > self.bband.lines.top and self.position:
         self.blueline = True

        #if self.dataclose > self.bband.lines.mid and not self.position and self.redline:
        if (
           self.dataclose > self.bband.lines.mid
           and self.t_macd.macd[0] > 0
           and  self.t_macd.macdsignal[0] > 0
           and not self.position and self.redline
           ):
            # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()
            trade_log(self,'buy') 
        #if self.dataclose > self.bband.lines.top and not self.position: 
        if (
           self.dataclose > self.bband.lines.top
           and self.t_macd.macd[0] > 0
           and  self.t_macd.macdsignal[0] > 0
           and not self.position
           ): 
            # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()
            trade_log(self,'buy')
        if self.dataclose < self.bband.lines.mid and self.position and self.blueline:
            # SELL, SELL, SELL!!! (with all possible default parameters)
            self.log('SELL CREATE, %.2f' % self.dataclose[0])
            self.blueline = False
            self.redline = False
            # Keep track of the created order to avoid a 2nd order
            self.order = self.sell()
            trade_log(self,'sell')
if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    cerebro.addstrategy(TestStrategy)

    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    #modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    #atapath = os.path.join(modpath, 'TSLA-USD.csv')

    # Create a Data Feed
    #data = bt.feeds.GenericCSVData(
        #dataname=datapath,
        # Do not pass values before this date
        #fromdate=datetime.datetime(2008, 4, 4),
        # Do not pass values before this date
        #todate=datetime.datetime(2016, 12, 2),

     #nullvalue=0.0,

     #dtformat=('%m/%d/%Y'),

     #datetime=0,
     #high=2,
     #low=3,
     #open=1,
     #close=4,
     #volume=5,
     #openinterest=-1)
 
    df = get_polonix()
    data = bt.feeds.PandasData(dataname=df) 

    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=5)

    # Set the commission
    cerebro.broker.setcommission(commission=0.002)

    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Plot the result
    cerebro.plot(style='candlestick')

  ###############################################################
#if ((self.talibb.macd[0] > self.talibb.macdsignal[0]) and (self.talibb.macd[-1] <= self.talibb.macdsignal[-1])) :

Модернизируем Backtrader стратегия полосы Болинджера

backtrader заточен под акции
упростим расчет профита
Backtrader стратегия полосы Болинджера

import datetime  # For datetime objects
import os.path  # To manage paths
import sys  # To find out the script name (in argv[0])

# Import the backtrader platform
import backtrader as bt
 
import requests
import json
import time
import math
from datetime import datetime
import pandas as pd 
 
price = 0
prof = 1


def trade_log(self, op) :
    global PRICE
    global profit
    global prof
    dt = self.datas[0].datetime.date(0)
    if op == 'buy':
        PRICE = self.dataclose[0]
        print(
             '%s, BUY  Покупка, Price: %.2f' %
             (dt.isoformat(), PRICE)
             )
    if op == 'sell':
         PRICE2 = self.dataclose[0]
         profit = PRICE2/PRICE-0.004
         prof = prof * profit
         print('%s, SELL Продажа, Price: %.2f, Cost: %.2f,  Profit: %.3f, Prof: %.3f' %
             (dt.isoformat(), PRICE2, PRICE, profit, prof)) 
 
def get_polonix() :
    time_depth = 500
    start_day = 500
    st_time=time.time()-start_day*24*60*60
    end_time=st_time+time_depth*60*60*24
    pair = 'USDT_BTC'

    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=1800" % (pair,st_time,end_time))
    resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=14400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=300" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=86400" % (pair,st_time,end_time))
    #resource=requests.get("https://poloniex.com/public?command=returnChartData&currencyPair=%s&start=%s&end=%s&period=21600" % (pair,st_time,end_time))

    data=[]
    chart_data={}
    chart_data = json.loads(resource.text)
    for elems in chart_data:
        data.append(elems)

    df = pd.DataFrame(data, columns=['date', 'open', 'high', 'low', 'close', 'volume'])
    df['openinterest']=0
    df['date'] = pd.to_datetime(df['date'], unit='s')
    #df = df[(df['date'] > '2018-1-1') & (df['date'] <= '2018-2-1')]
    #df = df[(df['date'] > '2017-9-1') & (df['date'] <= '2018-1-1')]
    df = df[(df['date'] >= '2018-4-1')]
    df = df.set_index('date')
    #print(df)
    return df 
 
# Create a Stratey
class TestStrategy(bt.Strategy):
    params = (('BBandsperiod', 20),)

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        dt = dt or self.datas[0].datetime.date(0)
        #print('%s, %s' % (dt.isoformat(), txt))

    def __init__(self):
        # Keep a reference to the "close" line in the data[0] dataseries
        self.dataclose = self.datas[0].close

        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.redline = None
        self.blueline = None

        # Add a BBand indicator
        self.bband = bt.indicators.BBands(self.datas[0], period=self.params.BBandsperiod)
        bt.indicators.MACDHisto(self.datas[0])
        rsi = bt.indicators.RSI(self.datas[0]) 
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return

        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed, order.Canceled, order.Margin]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))

                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))

            self.bar_executed = len(self)

        # Write down: no pending order
        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return

        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))

    

    def next(self):
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])

        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return

        if self.dataclose < self.bband.lines.bot and not self.position:
         self.redline = True

        if self.dataclose > self.bband.lines.top and self.position:
         self.blueline = True

        if self.dataclose > self.bband.lines.mid and not self.position and self.redline:         
         # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()
            trade_log(self,'buy') 
        if self.dataclose > self.bband.lines.top and not self.position:
            # BUY, BUY, BUY!!! (with all possible default parameters)
            self.log('BUY CREATE, %.2f' % self.dataclose[0])
            # Keep track of the created order to avoid a 2nd order
            self.order = self.buy()
            trade_log(self,'buy')
        if self.dataclose < self.bband.lines.mid and self.position and self.blueline:
            # SELL, SELL, SELL!!! (with all possible default parameters)
            self.log('SELL CREATE, %.2f' % self.dataclose[0])
            self.blueline = False
            self.redline = False
            # Keep track of the created order to avoid a 2nd order
            self.order = self.sell()
            trade_log(self,'sell')
if __name__ == '__main__':
    # Create a cerebro entity
    cerebro = bt.Cerebro()

    # Add a strategy
    cerebro.addstrategy(TestStrategy)

    # Datas are in a subfolder of the samples. Need to find where the script is
    # because it could have been called from anywhere
    #modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
    #atapath = os.path.join(modpath, 'TSLA-USD.csv')

    # Create a Data Feed
    #data = bt.feeds.GenericCSVData(
        #dataname=datapath,
        # Do not pass values before this date
        #fromdate=datetime.datetime(2008, 4, 4),
        # Do not pass values before this date
        #todate=datetime.datetime(2016, 12, 2),

     #nullvalue=0.0,

     #dtformat=('%m/%d/%Y'),

     #datetime=0,
     #high=2,
     #low=3,
     #open=1,
     #close=4,
     #volume=5,
     #openinterest=-1)
 
    df = get_polonix()
    data = bt.feeds.PandasData(dataname=df) 

    # Add the Data Feed to Cerebro
    cerebro.adddata(data)

    # Set our desired cash start
    cerebro.broker.setcash(100000.0)

    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=5)

    # Set the commission
    cerebro.broker.setcommission(commission=0.002)

    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Run over everything
    cerebro.run()

    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    # Plot the result
    cerebro.plot(style='candlestick')
 
########################################################################
2018-04-12, BUY  Покупка, Price: 7690.00
2018-04-16, SELL Продажа, Price: 8083.01, Cost: 7690.00,  Profit: 1.047, Prof: 1.047
2018-04-20, BUY  Покупка, Price: 8518.76
2018-04-25, SELL Продажа, Price: 8978.80, Cost: 8518.76,  Profit: 1.050, Prof: 1.099
2018-05-02, BUY  Покупка, Price: 9245.00
2018-05-06, SELL Продажа, Price: 9600.82, Cost: 9245.00,  Profit: 1.034, Prof: 1.137
2018-05-10, BUY  Покупка, Price: 9340.00
2018-05-15, SELL Продажа, Price: 8516.78, Cost: 9340.00,  Profit: 0.908, Prof: 1.033
2018-05-18, BUY  Покупка, Price: 8240.00
2018-05-22, SELL Продажа, Price: 8318.11, Cost: 8240.00,  Profit: 1.005, Prof: 1.038