首页 > 其他分享 >PyAlgoTrade-0-20-中文文档-四-

PyAlgoTrade-0-20-中文文档-四-

时间:2024-05-13 14:08:25浏览次数:21  
标签:INFO 00 .__ 20 self strategy instrument 文档 PyAlgoTrade

PyAlgoTrade 0.20 中文文档(四)

SMA 交叉

原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_sma_crossover.html

将此代码保存为 sma_crossover.py:

from pyalgotrade import strategy
from pyalgotrade.technical import ma
from pyalgotrade.technical import cross

class SMACrossOver(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, smaPeriod):
        super(SMACrossOver, self).__init__(feed)
        self.__instrument = instrument
        self.__position = None
        # We'll use adjusted close values instead of regular close values.
        self.setUseAdjustedValues(True)
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__sma = ma.SMA(self.__prices, smaPeriod)

    def getSMA(self):
        return self.__sma

    def onEnterCanceled(self, position):
        self.__position = None

    def onExitOk(self, position):
        self.__position = None

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        self.__position.exitMarket()

    def onBars(self, bars):
        # If a position was not opened, check if we should enter a long position.
        if self.__position is None:
            if cross.cross_above(self.__prices, self.__sma) > 0:
                shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice())
                # Enter a buy market order. The order is good till canceled.
                self.__position = self.enterLong(self.__instrument, shares, True)
        # Check if we have to exit the position.
        elif not self.__position.exitActive() and cross.cross_below(self.__prices, self.__sma) > 0:
            self.__position.exitMarket() 

并使用以下代码执行策略:

from __future__ import print_function

import sma_crossover
from pyalgotrade import plotter
from pyalgotrade.tools import quandl
from pyalgotrade.stratanalyzer import sharpe

def main(plot):
    instrument = "AAPL"
    smaPeriod = 163

    # Download the bars.
    feed = quandl.build_feed("WIKI", [instrument], 2011, 2012, ".")

    strat = sma_crossover.SMACrossOver(feed, instrument, smaPeriod)
    sharpeRatioAnalyzer = sharpe.SharpeRatio()
    strat.attachAnalyzer(sharpeRatioAnalyzer)

    if plot:
        plt = plotter.StrategyPlotter(strat, True, False, True)
        plt.getInstrumentSubplot(instrument).addDataSeries("sma", strat.getSMA())

    strat.run()
    print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05))

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

这是输出应该呈现的样子:

2017-07-24 22:56:58,112 quandl [INFO] Downloading AAPL 2011 to ./WIKI-AAPL-2011-quandl.csv
2017-07-24 22:57:02,364 quandl [INFO] Downloading AAPL 2012 to ./WIKI-AAPL-2012-quandl.csv
Sharpe ratio: 1.12

这是图表应该呈现的样子:

_images/sma_crossover.png

通过调整 sma 周期可以获得更好的回报。

使用移动平均线交叉的市场定时

原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_market_timing.html

这个示例是基于市场定时/GTAA 模型的描述:

该策略支持分析每个资产类别中的多个工具,并选择过去一个月收益最高的那个。

from __future__ import print_function

from pyalgotrade import strategy
from pyalgotrade import plotter
from pyalgotrade.barfeed import yahoofeed
from pyalgotrade.technical import ma
from pyalgotrade.technical import cumret
from pyalgotrade.stratanalyzer import sharpe
from pyalgotrade.stratanalyzer import returns

class MarketTiming(strategy.BacktestingStrategy):
    def __init__(self, feed, instrumentsByClass, initialCash):
        super(MarketTiming, self).__init__(feed, initialCash)
        self.setUseAdjustedValues(True)
        self.__instrumentsByClass = instrumentsByClass
        self.__rebalanceMonth = None
        self.__sharesToBuy = {}
        # Initialize indicators for each instrument.
        self.__sma = {}
        for assetClass in instrumentsByClass:
            for instrument in instrumentsByClass[assetClass]:
                priceDS = feed[instrument].getPriceDataSeries()
                self.__sma[instrument] = ma.SMA(priceDS, 200)

    def _shouldRebalance(self, dateTime):
        return dateTime.month != self.__rebalanceMonth

    def _getRank(self, instrument):
        # If the price is below the SMA, then this instrument doesn't rank at
        # all.
        smas = self.__sma[instrument]
        price = self.getLastPrice(instrument)
        if len(smas) == 0 or smas[-1] is None or price < smas[-1]:
            return None

        # Rank based on 20 day returns.
        ret = None
        lookBack = 20
        priceDS = self.getFeed()[instrument].getPriceDataSeries()
        if len(priceDS) >= lookBack and smas[-1] is not None and smas[-1*lookBack] is not None:
            ret = (priceDS[-1] - priceDS[-1*lookBack]) / float(priceDS[-1*lookBack])
        return ret

    def _getTopByClass(self, assetClass):
        # Find the instrument with the highest rank.
        ret = None
        highestRank = None
        for instrument in self.__instrumentsByClass[assetClass]:
            rank = self._getRank(instrument)
            if rank is not None and (highestRank is None or rank > highestRank):
                highestRank = rank
                ret = instrument
        return ret

    def _getTop(self):
        ret = {}
        for assetClass in self.__instrumentsByClass:
            ret[assetClass] = self._getTopByClass(assetClass)
        return ret

    def _placePendingOrders(self):
        # Use less chash just in case price changes too much.
        remainingCash = round(self.getBroker().getCash() * 0.9, 2)

        for instrument in self.__sharesToBuy:
            orderSize = self.__sharesToBuy[instrument]
            if orderSize > 0:
                # Adjust the order size based on available cash.
                lastPrice = self.getLastPrice(instrument)
                cost = orderSize * lastPrice
                while cost > remainingCash and orderSize > 0:
                    orderSize -= 1
                    cost = orderSize * lastPrice
                if orderSize > 0:
                    remainingCash -= cost
                    assert(remainingCash >= 0)

            if orderSize != 0:
                self.info("Placing market order for %d  %s shares" % (orderSize, instrument))
                self.marketOrder(instrument, orderSize, goodTillCanceled=True)
                self.__sharesToBuy[instrument] -= orderSize

    def _logPosSize(self):
        totalEquity = self.getBroker().getEquity()
        positions = self.getBroker().getPositions()
        for instrument in self.getBroker().getPositions():
            posSize = positions[instrument] * self.getLastPrice(instrument) / totalEquity * 100
            self.info("%s - %0.2f  %%" % (instrument, posSize))

    def _rebalance(self):
        self.info("Rebalancing")

        # Cancel all active/pending orders.
        for order in self.getBroker().getActiveOrders():
            self.getBroker().cancelOrder(order)

        cashPerAssetClass = round(self.getBroker().getEquity() / float(len(self.__instrumentsByClass)), 2)
        self.__sharesToBuy = {}

        # Calculate which positions should be open during the next period.
        topByClass = self._getTop()
        for assetClass in topByClass:
            instrument = topByClass[assetClass]
            self.info("Best for class %s: %s" % (assetClass, instrument))
            if instrument is not None:
                lastPrice = self.getLastPrice(instrument)
                cashForInstrument = round(cashPerAssetClass - self.getBroker().getShares(instrument) * lastPrice, 2)
                # This may yield a negative value and we have to reduce this
                # position.
                self.__sharesToBuy[instrument] = int(cashForInstrument / lastPrice)

        # Calculate which positions should be closed.
        for instrument in self.getBroker().getPositions():
            if instrument not in topByClass.values():
                currentShares = self.getBroker().getShares(instrument)
                assert(instrument not in self.__sharesToBuy)
                self.__sharesToBuy[instrument] = currentShares * -1

    def getSMA(self, instrument):
        return self.__sma[instrument]

    def onBars(self, bars):
        currentDateTime = bars.getDateTime()

        if self._shouldRebalance(currentDateTime):
            self.__rebalanceMonth = currentDateTime.month
            self._rebalance()

        self._placePendingOrders()

def main(plot):
    initialCash = 10000
    instrumentsByClass = {
        "US Stocks": ["VTI"],
        "Foreign Stocks": ["VEU"],
        "US 10 Year Government Bonds": ["IEF"],
        "Real Estate": ["VNQ"],
        "Commodities": ["DBC"],
    }

    # Load the bars. These files were manually downloaded from Yahoo Finance.
    feed = yahoofeed.Feed()
    instruments = ["SPY"]
    for assetClass in instrumentsByClass:
        instruments.extend(instrumentsByClass[assetClass])

    for year in range(2007, 2013+1):
        for instrument in instruments:
            fileName = "%s-%d-yahoofinance.csv" % (instrument, year)
            print("Loading bars from %s" % fileName)
            feed.addBarsFromCSV(instrument, fileName)

    # Build the strategy and attach some metrics.
    strat = MarketTiming(feed, instrumentsByClass, initialCash)
    sharpeRatioAnalyzer = sharpe.SharpeRatio()
    strat.attachAnalyzer(sharpeRatioAnalyzer)
    returnsAnalyzer = returns.Returns()
    strat.attachAnalyzer(returnsAnalyzer)

    if plot:
        plt = plotter.StrategyPlotter(strat, False, False, True)
        plt.getOrCreateSubplot("cash").addCallback("Cash", lambda x: strat.getBroker().getCash())
        # Plot strategy vs. SPY cumulative returns.
        plt.getOrCreateSubplot("returns").addDataSeries("SPY", cumret.CumulativeReturn(feed["SPY"].getPriceDataSeries()))
        plt.getOrCreateSubplot("returns").addDataSeries("Strategy", returnsAnalyzer.getCumulativeReturns())

    strat.run()
    print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05))
    print("Returns: %.2f  %%" % (returnsAnalyzer.getCumulativeReturns()[-1] * 100))

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

输出应该是这样的:

Loading bars from SPY-2007-yahoofinance.csv
Loading bars from VTI-2007-yahoofinance.csv
Loading bars from DBC-2007-yahoofinance.csv
Loading bars from IEF-2007-yahoofinance.csv
Loading bars from VEU-2007-yahoofinance.csv
Loading bars from VNQ-2007-yahoofinance.csv
Loading bars from SPY-2008-yahoofinance.csv
Loading bars from VTI-2008-yahoofinance.csv
Loading bars from DBC-2008-yahoofinance.csv
Loading bars from IEF-2008-yahoofinance.csv
.
.
.
2013-10-01 00:00:00 strategy [INFO] Best for class US Stocks: VTI
2013-10-01 00:00:00 strategy [INFO] Best for class Commodities: None
2013-10-01 00:00:00 strategy [INFO] Best for class US 10 Year Government Bonds: None
2013-10-01 00:00:00 strategy [INFO] Best for class Foreign Stocks: VEU
2013-10-01 00:00:00 strategy [INFO] Best for class Real Estate: None
2013-10-01 00:00:00 strategy [INFO] Placing market order for -2 VEU shares
2013-11-01 00:00:00 strategy [INFO] Rebalancing
2013-11-01 00:00:00 strategy [INFO] Best for class US Stocks: VTI
2013-11-01 00:00:00 strategy [INFO] Best for class Commodities: None
2013-11-01 00:00:00 strategy [INFO] Best for class US 10 Year Government Bonds: None
2013-11-01 00:00:00 strategy [INFO] Best for class Foreign Stocks: VEU
2013-11-01 00:00:00 strategy [INFO] Best for class Real Estate: VNQ
2013-11-01 00:00:00 strategy [INFO] Placing market order for -1 VTI shares
2013-11-01 00:00:00 strategy [INFO] Placing market order for -1 VEU shares
2013-11-01 00:00:00 strategy [INFO] Placing market order for 39 VNQ shares
2013-12-02 00:00:00 strategy [INFO] Rebalancing
2013-12-02 00:00:00 strategy [INFO] Best for class US Stocks: VTI
2013-12-02 00:00:00 strategy [INFO] Best for class Commodities: None
2013-12-02 00:00:00 strategy [INFO] Best for class US 10 Year Government Bonds: None
2013-12-02 00:00:00 strategy [INFO] Best for class Foreign Stocks: VEU
2013-12-02 00:00:00 strategy [INFO] Best for class Real Estate: None
2013-12-02 00:00:00 strategy [INFO] Placing market order for -1 VTI shares
2013-12-02 00:00:00 strategy [INFO] Placing market order for -39 VNQ shares
Sharpe ratio: -0.06
Returns: 32.97 %

图表应该是这样的:

_images/market_timing.png

Ernie Chan 的黄金与黄金矿业公司

原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_statarb_erniechan.html

此示例基于:

from __future__ import print_function

from pyalgotrade import strategy
from pyalgotrade import dataseries
from pyalgotrade.dataseries import aligned
from pyalgotrade import plotter
from pyalgotrade.barfeed import yahoofeed
from pyalgotrade.stratanalyzer import sharpe

import numpy as np
import statsmodels.api as sm

def get_beta(values1, values2):
    # http://statsmodels.sourceforge.net/stable/regression.html
    model = sm.OLS(values1, values2)
    results = model.fit()
    return results.params[0]

class StatArbHelper:
    def __init__(self, ds1, ds2, windowSize):
        # We're going to use datetime aligned versions of the dataseries.
        self.__ds1, self.__ds2 = aligned.datetime_aligned(ds1, ds2)
        self.__windowSize = windowSize
        self.__hedgeRatio = None
        self.__spread = None
        self.__spreadMean = None
        self.__spreadStd = None
        self.__zScore = None

    def getSpread(self):
        return self.__spread

    def getSpreadMean(self):
        return self.__spreadMean

    def getSpreadStd(self):
        return self.__spreadStd

    def getZScore(self):
        return self.__zScore

    def getHedgeRatio(self):
        return self.__hedgeRatio

    def __updateHedgeRatio(self, values1, values2):
        self.__hedgeRatio = get_beta(values1, values2)

    def __updateSpreadMeanAndStd(self, values1, values2):
        if self.__hedgeRatio is not None:
            spread = values1 - values2 * self.__hedgeRatio
            self.__spreadMean = spread.mean()
            self.__spreadStd = spread.std(ddof=1)

    def __updateSpread(self):
        if self.__hedgeRatio is not None:
            self.__spread = self.__ds1[-1] - self.__hedgeRatio * self.__ds2[-1]

    def __updateZScore(self):
        if self.__spread is not None and self.__spreadMean is not None and self.__spreadStd is not None:
            self.__zScore = (self.__spread - self.__spreadMean) / float(self.__spreadStd)

    def update(self):
        if len(self.__ds1) >= self.__windowSize:
            values1 = np.asarray(self.__ds1[-1*self.__windowSize:])
            values2 = np.asarray(self.__ds2[-1*self.__windowSize:])
            self.__updateHedgeRatio(values1, values2)
            self.__updateSpread()
            self.__updateSpreadMeanAndStd(values1, values2)
            self.__updateZScore()

class StatArb(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument1, instrument2, windowSize):
        super(StatArb, self).__init__(feed)
        self.setUseAdjustedValues(True)
        self.__statArbHelper = StatArbHelper(feed[instrument1].getAdjCloseDataSeries(), feed[instrument2].getAdjCloseDataSeries(), windowSize)
        self.__i1 = instrument1
        self.__i2 = instrument2

        # These are used only for plotting purposes.
        self.__spread = dataseries.SequenceDataSeries()
        self.__hedgeRatio = dataseries.SequenceDataSeries()

    def getSpreadDS(self):
        return self.__spread

    def getHedgeRatioDS(self):
        return self.__hedgeRatio

    def __getOrderSize(self, bars, hedgeRatio):
        cash = self.getBroker().getCash(False)
        price1 = bars[self.__i1].getAdjClose()
        price2 = bars[self.__i2].getAdjClose()
        size1 = int(cash / (price1 + hedgeRatio * price2))
        size2 = int(size1 * hedgeRatio)
        return (size1, size2)

    def buySpread(self, bars, hedgeRatio):
        amount1, amount2 = self.__getOrderSize(bars, hedgeRatio)
        self.marketOrder(self.__i1, amount1)
        self.marketOrder(self.__i2, amount2 * -1)

    def sellSpread(self, bars, hedgeRatio):
        amount1, amount2 = self.__getOrderSize(bars, hedgeRatio)
        self.marketOrder(self.__i1, amount1 * -1)
        self.marketOrder(self.__i2, amount2)

    def reducePosition(self, instrument):
        currentPos = self.getBroker().getShares(instrument)
        if currentPos > 0:
            self.marketOrder(instrument, currentPos * -1)
        elif currentPos < 0:
            self.marketOrder(instrument, currentPos * -1)

    def onBars(self, bars):
        self.__statArbHelper.update()

        # These is used only for plotting purposes.
        self.__spread.appendWithDateTime(bars.getDateTime(), self.__statArbHelper.getSpread())
        self.__hedgeRatio.appendWithDateTime(bars.getDateTime(), self.__statArbHelper.getHedgeRatio())

        if bars.getBar(self.__i1) and bars.getBar(self.__i2):
            hedgeRatio = self.__statArbHelper.getHedgeRatio()
            zScore = self.__statArbHelper.getZScore()
            if zScore is not None:
                currentPos = abs(self.getBroker().getShares(self.__i1)) + abs(self.getBroker().getShares(self.__i2))
                if abs(zScore) <= 1 and currentPos != 0:
                    self.reducePosition(self.__i1)
                    self.reducePosition(self.__i2)
                elif zScore <= -2 and currentPos == 0:  # Buy spread when its value drops below 2 standard deviations.
                    self.buySpread(bars, hedgeRatio)
                elif zScore >= 2 and currentPos == 0:  # Short spread when its value rises above 2 standard deviations.
                    self.sellSpread(bars, hedgeRatio)

def main(plot):
    instruments = ["gld", "gdx"]
    windowSize = 50

    # Load the bars. These files were manually downloaded from Yahoo Finance.
    feed = yahoofeed.Feed()
    for year in range(2006, 2012+1):
        for instrument in instruments:
            fileName = "%s-%d-yahoofinance.csv" % (instrument, year)
            print("Loading bars from %s" % fileName)
            feed.addBarsFromCSV(instrument, fileName)

    strat = StatArb(feed, instruments[0], instruments[1], windowSize)
    sharpeRatioAnalyzer = sharpe.SharpeRatio()
    strat.attachAnalyzer(sharpeRatioAnalyzer)

    if plot:
        plt = plotter.StrategyPlotter(strat, False, False, True)
        plt.getOrCreateSubplot("hedge").addDataSeries("Hedge Ratio", strat.getHedgeRatioDS())
        plt.getOrCreateSubplot("spread").addDataSeries("Spread", strat.getSpreadDS())

    strat.run()
    print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05))

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

这是输出应该的样子:

Loading bars from gld-2006-yahoofinance.csv
Loading bars from gdx-2006-yahoofinance.csv
Loading bars from gld-2007-yahoofinance.csv
Loading bars from gdx-2007-yahoofinance.csv
Loading bars from gld-2008-yahoofinance.csv
Loading bars from gdx-2008-yahoofinance.csv
Loading bars from gld-2009-yahoofinance.csv
Loading bars from gdx-2009-yahoofinance.csv
Loading bars from gld-2010-yahoofinance.csv
Loading bars from gdx-2010-yahoofinance.csv
Loading bars from gld-2011-yahoofinance.csv
Loading bars from gdx-2011-yahoofinance.csv
Loading bars from gld-2012-yahoofinance.csv
Loading bars from gdx-2012-yahoofinance.csv
Sharpe ratio: -0.20

这是图表应该的样子:

_images/statarb_erniechan.png

通过调整窗口大小以及 z-score 的入口和出口值,您可以获得更好的回报。

布林带

原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_bbands.html

此示例基于:

from __future__ import print_function

from pyalgotrade import strategy
from pyalgotrade import plotter
from pyalgotrade.tools import quandl
from pyalgotrade.technical import bollinger
from pyalgotrade.stratanalyzer import sharpe
from pyalgotrade import broker as basebroker

class BBands(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, bBandsPeriod):
        super(BBands, self).__init__(feed)
        self.__instrument = instrument
        self.__bbands = bollinger.BollingerBands(feed[instrument].getCloseDataSeries(), bBandsPeriod, 2)

    def getBollingerBands(self):
        return self.__bbands

    def onOrderUpdated(self, order):
        if order.isBuy():
            orderType = "Buy"
        else:
            orderType = "Sell"
        self.info("%s order %d updated - Status: %s" % (
            orderType, order.getId(), basebroker.Order.State.toString(order.getState())
        ))

    def onBars(self, bars):
        lower = self.__bbands.getLowerBand()[-1]
        upper = self.__bbands.getUpperBand()[-1]
        if lower is None:
            return

        shares = self.getBroker().getShares(self.__instrument)
        bar = bars[self.__instrument]
        if shares == 0 and bar.getClose() < lower:
            sharesToBuy = int(self.getBroker().getCash(False) / bar.getClose())
            self.info("Placing buy market order for %s shares" % sharesToBuy)
            self.marketOrder(self.__instrument, sharesToBuy)
        elif shares > 0 and bar.getClose() > upper:
            self.info("Placing sell market order for %s shares" % shares)
            self.marketOrder(self.__instrument, -1*shares)

def main(plot):
    instrument = "yhoo"
    bBandsPeriod = 40

    # Download the bars.
    feed = quandl.build_feed("WIKI", [instrument], 2011, 2012, ".")

    strat = BBands(feed, instrument, bBandsPeriod)
    sharpeRatioAnalyzer = sharpe.SharpeRatio()
    strat.attachAnalyzer(sharpeRatioAnalyzer)

    if plot:
        plt = plotter.StrategyPlotter(strat, True, True, True)
        plt.getInstrumentSubplot(instrument).addDataSeries("upper", strat.getBollingerBands().getUpperBand())
        plt.getInstrumentSubplot(instrument).addDataSeries("middle", strat.getBollingerBands().getMiddleBand())
        plt.getInstrumentSubplot(instrument).addDataSeries("lower", strat.getBollingerBands().getLowerBand())

    strat.run()
    print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05))

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

这就是输出的样子:

2011-07-20 00:00:00 strategy [INFO] Placing buy market order for 74183 shares
2011-07-20 00:00:00 strategy [INFO] Buy order 1 updated - Status: SUBMITTED
2011-07-21 00:00:00 strategy [INFO] Buy order 1 updated - Status: ACCEPTED
2011-07-21 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [1] for 74183 share/s
2011-07-21 00:00:00 strategy [INFO] Buy order 1 updated - Status: CANCELED
2011-07-21 00:00:00 strategy [INFO] Placing buy market order for 73583 shares
2011-07-21 00:00:00 strategy [INFO] Buy order 2 updated - Status: SUBMITTED
2011-07-22 00:00:00 strategy [INFO] Buy order 2 updated - Status: ACCEPTED
2011-07-22 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [2] for 73583 share/s
2011-07-22 00:00:00 strategy [INFO] Buy order 2 updated - Status: CANCELED
2011-07-25 00:00:00 strategy [INFO] Placing buy market order for 73046 shares
2011-07-25 00:00:00 strategy [INFO] Buy order 3 updated - Status: SUBMITTED
2011-07-26 00:00:00 strategy [INFO] Buy order 3 updated - Status: ACCEPTED
2011-07-26 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [3] for 73046 share/s
2011-07-26 00:00:00 strategy [INFO] Buy order 3 updated - Status: CANCELED
2011-07-27 00:00:00 strategy [INFO] Placing buy market order for 73610 shares
2011-07-27 00:00:00 strategy [INFO] Buy order 4 updated - Status: SUBMITTED
2011-07-28 00:00:00 strategy [INFO] Buy order 4 updated - Status: ACCEPTED
2011-07-28 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [4] for 73610 share/s
2011-07-28 00:00:00 strategy [INFO] Buy order 4 updated - Status: CANCELED
2011-07-28 00:00:00 strategy [INFO] Placing buy market order for 74074 shares
2011-07-28 00:00:00 strategy [INFO] Buy order 5 updated - Status: SUBMITTED
2011-07-29 00:00:00 strategy [INFO] Buy order 5 updated - Status: ACCEPTED
2011-07-29 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [5] for 74074 share/s
2011-07-29 00:00:00 strategy [INFO] Buy order 5 updated - Status: CANCELED
2011-07-29 00:00:00 strategy [INFO] Placing buy market order for 76335 shares
2011-07-29 00:00:00 strategy [INFO] Buy order 6 updated - Status: SUBMITTED
2011-08-01 00:00:00 strategy [INFO] Buy order 6 updated - Status: ACCEPTED
2011-08-01 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [6] for 76335 share/s
2011-08-01 00:00:00 strategy [INFO] Buy order 6 updated - Status: CANCELED
2011-08-01 00:00:00 strategy [INFO] Placing buy market order for 76335 shares
2011-08-01 00:00:00 strategy [INFO] Buy order 7 updated - Status: SUBMITTED
2011-08-02 00:00:00 strategy [INFO] Buy order 7 updated - Status: ACCEPTED
2011-08-02 00:00:00 strategy [INFO] Buy order 7 updated - Status: FILLED
2011-09-15 00:00:00 strategy [INFO] Placing sell market order for 76335 shares
2011-09-15 00:00:00 strategy [INFO] Sell order 8 updated - Status: SUBMITTED
2011-09-16 00:00:00 strategy [INFO] Sell order 8 updated - Status: ACCEPTED
2011-09-16 00:00:00 strategy [INFO] Sell order 8 updated - Status: FILLED
2012-02-17 00:00:00 strategy [INFO] Placing buy market order for 77454 shares
2012-02-17 00:00:00 strategy [INFO] Buy order 9 updated - Status: SUBMITTED
2012-02-21 00:00:00 strategy [INFO] Buy order 9 updated - Status: ACCEPTED
2012-02-21 00:00:00 broker.backtesting [DEBUG] Not enough cash to fill yhoo order [9] for 77454 share/s
2012-02-21 00:00:00 strategy [INFO] Buy order 9 updated - Status: CANCELED
2012-02-21 00:00:00 strategy [INFO] Placing buy market order for 78819 shares
2012-02-21 00:00:00 strategy [INFO] Buy order 10 updated - Status: SUBMITTED
2012-02-22 00:00:00 strategy [INFO] Buy order 10 updated - Status: ACCEPTED
2012-02-22 00:00:00 strategy [INFO] Buy order 10 updated - Status: FILLED
2012-06-29 00:00:00 strategy [INFO] Placing sell market order for 78819 shares
2012-06-29 00:00:00 strategy [INFO] Sell order 11 updated - Status: SUBMITTED
2012-07-02 00:00:00 strategy [INFO] Sell order 11 updated - Status: ACCEPTED
2012-07-02 00:00:00 strategy [INFO] Sell order 11 updated - Status: FILLED
2012-08-10 00:00:00 strategy [INFO] Placing buy market order for 82565 shares
2012-08-10 00:00:00 strategy [INFO] Buy order 12 updated - Status: SUBMITTED
2012-08-13 00:00:00 strategy [INFO] Buy order 12 updated - Status: ACCEPTED
2012-08-13 00:00:00 strategy [INFO] Buy order 12 updated - Status: FILLED
2012-10-23 00:00:00 strategy [INFO] Placing sell market order for 82565 shares
2012-10-23 00:00:00 strategy [INFO] Sell order 13 updated - Status: SUBMITTED
2012-10-24 00:00:00 strategy [INFO] Sell order 13 updated - Status: ACCEPTED
2012-10-24 00:00:00 strategy [INFO] Sell order 13 updated - Status: FILLED
Sharpe ratio: 0.71

这就是图表的样子:

_images/bbands.png

通过调整布林带的周期以及进出点,您可以获得更好的回报。

RSI2

原文链接:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_rsi2.html

此示例基于一种称为 RSI2 的策略(stockcharts.com/school/doku.php?id=chart_school:trading_strategies:rsi2),需要以下参数:

  • 用于趋势识别的 SMA 周期。我们将其称为 entrySMA。
  • 用于退出点的较小 SMA 周期。我们将其称为 exitSMA。
  • 一个用于进入多空仓位的 RSI 期间。我们将其称为 rsiPeriod。
  • 一个用于多仓位进入的 RSI 超卖阈值。我们将其称为 overSoldThreshold。
  • 用于空仓位进入的 RSI 超买阈值。我们将其称为 overBoughtThreshold。

将此代码保存为 rsi2.py:

from pyalgotrade import strategy
from pyalgotrade.technical import ma
from pyalgotrade.technical import rsi
from pyalgotrade.technical import cross

class RSI2(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, entrySMA, exitSMA, rsiPeriod, overBoughtThreshold, overSoldThreshold):
        super(RSI2, self).__init__(feed)
        self.__instrument = instrument
        # We'll use adjusted close values, if available, instead of regular close values.
        if feed.barsHaveAdjClose():
            self.setUseAdjustedValues(True)
        self.__priceDS = feed[instrument].getPriceDataSeries()
        self.__entrySMA = ma.SMA(self.__priceDS, entrySMA)
        self.__exitSMA = ma.SMA(self.__priceDS, exitSMA)
        self.__rsi = rsi.RSI(self.__priceDS, rsiPeriod)
        self.__overBoughtThreshold = overBoughtThreshold
        self.__overSoldThreshold = overSoldThreshold
        self.__longPos = None
        self.__shortPos = None

    def getEntrySMA(self):
        return self.__entrySMA

    def getExitSMA(self):
        return self.__exitSMA

    def getRSI(self):
        return self.__rsi

    def onEnterCanceled(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitOk(self, position):
        if self.__longPos == position:
            self.__longPos = None
        elif self.__shortPos == position:
            self.__shortPos = None
        else:
            assert(False)

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        position.exitMarket()

    def onBars(self, bars):
        # Wait for enough bars to be available to calculate SMA and RSI.
        if self.__exitSMA[-1] is None or self.__entrySMA[-1] is None or self.__rsi[-1] is None:
            return

        bar = bars[self.__instrument]
        if self.__longPos is not None:
            if self.exitLongSignal():
                self.__longPos.exitMarket()
        elif self.__shortPos is not None:
            if self.exitShortSignal():
                self.__shortPos.exitMarket()
        else:
            if self.enterLongSignal(bar):
                shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice())
                self.__longPos = self.enterLong(self.__instrument, shares, True)
            elif self.enterShortSignal(bar):
                shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice())
                self.__shortPos = self.enterShort(self.__instrument, shares, True)

    def enterLongSignal(self, bar):
        return bar.getPrice() > self.__entrySMA[-1] and self.__rsi[-1] <= self.__overSoldThreshold

    def exitLongSignal(self):
        return cross.cross_above(self.__priceDS, self.__exitSMA) and not self.__longPos.exitActive()

    def enterShortSignal(self, bar):
        return bar.getPrice() < self.__entrySMA[-1] and self.__rsi[-1] >= self.__overBoughtThreshold

    def exitShortSignal(self):
        return cross.cross_below(self.__priceDS, self.__exitSMA) and not self.__shortPos.exitActive() 

并使用以下代码执行策略:

from __future__ import print_function

import rsi2
from pyalgotrade import plotter
from pyalgotrade.barfeed import yahoofeed
from pyalgotrade.stratanalyzer import sharpe

def main(plot):
    instrument = "DIA"
    entrySMA = 200
    exitSMA = 5
    rsiPeriod = 2
    overBoughtThreshold = 90
    overSoldThreshold = 10

    # Load the bars. These files were manually downloaded from Yahoo Finance.
    feed = yahoofeed.Feed()
    for year in range(2009, 2013):
        fileName = "%s-%d-yahoofinance.csv" % (instrument, year)
        print("Loading bars from %s" % fileName)
        feed.addBarsFromCSV(instrument, fileName)

    strat = rsi2.RSI2(feed, instrument, entrySMA, exitSMA, rsiPeriod, overBoughtThreshold, overSoldThreshold)
    sharpeRatioAnalyzer = sharpe.SharpeRatio()
    strat.attachAnalyzer(sharpeRatioAnalyzer)

    if plot:
        plt = plotter.StrategyPlotter(strat, True, False, True)
        plt.getInstrumentSubplot(instrument).addDataSeries("Entry SMA", strat.getEntrySMA())
        plt.getInstrumentSubplot(instrument).addDataSeries("Exit SMA", strat.getExitSMA())
        plt.getOrCreateSubplot("rsi").addDataSeries("RSI", strat.getRSI())
        plt.getOrCreateSubplot("rsi").addLine("Overbought", overBoughtThreshold)
        plt.getOrCreateSubplot("rsi").addLine("Oversold", overSoldThreshold)

    strat.run()
    print("Sharpe ratio: %.2f" % sharpeRatioAnalyzer.getSharpeRatio(0.05))

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

输出应该如下所示:

Loading bars from DIA-2009-yahoofinance.csv
Loading bars from DIA-2010-yahoofinance.csv
Loading bars from DIA-2011-yahoofinance.csv
Loading bars from DIA-2012-yahoofinance.csv
Sharpe ratio: -0.11

并且图表应该如下所示:

_images/rsi2_sample.png

通过调整不同参数,您可以获得更好的回报。

Quandl 整合

原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/sample_quandl.html

这个示例的目的是展示如何将来自 Quandl 的价格数据以及任何时间序列数据以 CSV 格式整合到策略中。

我们将使用来自 Quandl 的以下 CSV 数据:www.quandl.com/OFDP-Open-Financial-Data-Project/GOLD_2-LBMA-Gold-Price-London-Fixings-P-M

from pyalgotrade import strategy
from pyalgotrade import plotter
from pyalgotrade.tools import quandl
from pyalgotrade.feed import csvfeed
import datetime

class MyStrategy(strategy.BacktestingStrategy):
    def __init__(self, feed, quandlFeed, instrument):
        super(MyStrategy, self).__init__(feed)
        self.setUseAdjustedValues(True)
        self.__instrument = instrument

        # It is VERY important to add the the extra feed to the event dispatch loop before
        # running the strategy.
        self.getDispatcher().addSubject(quandlFeed)

        # Subscribe to events from the Quandl feed.
        quandlFeed.getNewValuesEvent().subscribe(self.onQuandlData)

    def onQuandlData(self, dateTime, values):
        self.info(values)

    def onBars(self, bars):
        self.info(bars[self.__instrument].getAdjClose())

def main(plot):
    instruments = ["GORO"]

    # Download GORO bars using WIKI source code.
    feed = quandl.build_feed("WIKI", instruments, 2006, 2012, ".")

    # Load Quandl CSV downloaded from http://www.quandl.com/OFDP-Open-Financial-Data-Project/GOLD_2-LBMA-Gold-Price-London-Fixings-P-M
    quandlFeed = csvfeed.Feed("Date", "%Y-%m-%d")
    quandlFeed.setDateRange(datetime.datetime(2006, 1, 1), datetime.datetime(2012, 12, 31))
    quandlFeed.addValuesFromCSV("quandl_gold_2.csv")

    myStrategy = MyStrategy(feed, quandlFeed, instruments[0])

    if plot:
        plt = plotter.StrategyPlotter(myStrategy, True, False, False)
        plt.getOrCreateSubplot("quandl").addDataSeries("USD", quandlFeed["USD"])
        plt.getOrCreateSubplot("quandl").addDataSeries("EUR", quandlFeed["EUR"])
        plt.getOrCreateSubplot("quandl").addDataSeries("GBP", quandlFeed["GBP"])

    myStrategy.run()

    if plot:
        plt.plot()

if __name__ == "__main__":
    main(True) 

输出应该如下所示:

2006-01-01 00:00:00 strategy [INFO] {'USD': 513.0, 'GBP': 298.204, 'EUR': 433.533}
2006-01-08 00:00:00 strategy [INFO] {'USD': 535.25, 'GBP': 302.572, 'EUR': 440.173}
2006-01-15 00:00:00 strategy [INFO] {'USD': 548.25, 'GBP': 309.781, 'EUR': 454.489}
2006-01-22 00:00:00 strategy [INFO] {'USD': 567.25, 'GBP': 321.152, 'EUR': 468.802}
2006-01-29 00:00:00 strategy [INFO] {'USD': 561.75, 'GBP': 315.147, 'EUR': 460.526}
2006-02-05 00:00:00 strategy [INFO] {'USD': 569.0, 'GBP': 322.562, 'EUR': 474.167}
2006-02-12 00:00:00 strategy [INFO] {'USD': 557.0, 'GBP': 317.198, 'EUR': 463.78}
2006-02-19 00:00:00 strategy [INFO] {'USD': 551.7, 'GBP': 317.251, 'EUR': 463.224}
2006-02-26 00:00:00 strategy [INFO] {'USD': 554.15, 'GBP': 316.838, 'EUR': 465.555}
2006-03-05 00:00:00 strategy [INFO] {'USD': 565.0, 'GBP': 322.029, 'EUR': 469.854}
.
.
.
2012-12-19 00:00:00 strategy [INFO] 15.43
2012-12-20 00:00:00 strategy [INFO] 15.39
2012-12-21 00:00:00 strategy [INFO] 15.35
2012-12-23 00:00:00 strategy [INFO] {'USD': 1651.5, 'GBP': 1019.256, 'EUR': 1253.701}
2012-12-24 00:00:00 strategy [INFO] 15.2
2012-12-26 00:00:00 strategy [INFO] 15.56
2012-12-27 00:00:00 strategy [INFO] 15.24
2012-12-28 00:00:00 strategy [INFO] 15.09
2012-12-30 00:00:00 strategy [INFO] {'USD': 1657.5, 'GBP': 1027.206, 'EUR': 1253.024}
2012-12-31 00:00:00 strategy [INFO] 15.41

而这个图表应该是这样的:

_images/quandl_sample.png

标签:INFO,00,.__,20,self,strategy,instrument,文档,PyAlgoTrade
From: https://www.cnblogs.com/apachecn/p/18189081

相关文章

  • PyAlgoTrade-0-20-中文文档-三-
    PyAlgoTrade0.20中文文档(三)工具原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/tools.htmlQuandlpyalgotrade.tools.quandl.``build_feed(sourceCode,tableCodes,fromYear,toYear,storage,frequency=86400,timezone=None,skipErrors=False,authToken=None,columnNames={......
  • PyAlgoTrade-0-20-中文文档-二-
    PyAlgoTrade0.20中文文档(二)经纪人-订单管理类原文:gbeced.github.io/pyalgotrade/docs/v0.20/html/broker.html基础模块和类类pyalgotrade.broker.``Order(type_,action,instrument,quantity,instrumentTraits)基类:object订单的基类。参数:type(Order.Type)–订单类......
  • Zipline-3-0-中文文档-一-
    Zipline3.0中文文档(一)原文:zipline.ml4trading.io回测您的交易策略原文:zipline.ml4trading.io/index.htmlZipline是一个用于回测的Pythonic事件驱动系统,由众包投资基金Quantopian开发和使用,作为回测和实时交易引擎。自2020年底关闭以来,托管这些文档的域名已过期。......
  • C120 树剖+李超树 P4069 [SDOI2016] 游戏
    视频链接:C120树剖+李超树P4069[SDOI2016]游戏_哔哩哔哩_bilibili    D12LuoguP3384【模板】轻重链剖分/树链剖分-董晓-博客园(cnblogs.com) LuoguP4069[SDOI2016]游戏//树剖+李超树O(nlognlognlogn)#include<iostream>#include<cstring>#in......
  • 洛谷题单指南-动态规划3-P3205 [HNOI2010] 合唱队
    原题链接:https://www.luogu.com.cn/problem/P3205题意解读:给定理想队形,计算初始队形的方案数。解题思路:对于给定理想队形,最后一个人插入有两种可能:从左边插入、从右边插入从左边插入,则意味着前一个数比当前数大,前一个数有可能在左边也有可能在右边从右边插入,则意味着前一个数......
  • 软工计算1—Java篇1 20240513
    Java中的函数重载函数重载(FunctionOverloading)是面向对象编程中的一个概念,它允许在同一个类中定义多个同名函数,但这些函数的参数列表必须不同。参数列表的不同可以体现在参数的类型、数量或顺序上。函数重载使得程序设计更加灵活,可以针对不同的参数类型或数量提供不同的函数实现......
  • P9425 [蓝桥杯 2022 国 B] 2022
    一、题目描述将\(2022\)拆分成\(10\)个互不相同的正整数之和,有多少种方案?二、问题简析令\(dp[i][j]=\)\(i\)的\(j\)划分的方案数(满足互不相同的正整数)。有两种实现方式:\(dp[i][j]\)不含\(1\)在\(dp[i-j][j]\)的基础上,每个元素+1。有\(j\)个元素,每个元素+1,......
  • 2024广东大学生攻防大赛WP
    Misc猜一猜题目描述:你们想要的flag就在压缩包里面。压缩包文件名解密解压密码为a1478520然后修改flag.png文件头得到扫描二维码之后❀❁❀❇❀✼❀❂✿❆✿✽❁❀✿✾❂❅✿❄❂❉❀✿❂❆❀❃❀✿❂❆✿❀❁✾✻✿❁❁❀❁❂❊✻❂✿❈=花朵解密https://www.qq......
  • sqlserver2019安装
    说明:新版sqlserver安装分两部分:第一部分安装服务 第二部分安装管理工具 第一步:下载安装包 ed2k://|file|cn_office_professional_plus_2019_x86_x64_dvd_5e5be643.iso|3775004672|1E4FFA5240F21F60DC027F73F1C62FF4|/第二步:安装服务这里注意:    推荐第一种安......
  • EXP练手:CVE-2022-22963从编写到调试排错
    写什么?之前在使用Spring相关工具时候发现其中漏洞利用模块CVE-2022-22963需要手动利用(2023年的笔记,现在不确认工具是否更新了)GitHub-AabyssZG/SpringBoot-Scan:针对SpringBoot的开源渗透框架,以及Spring相关高危漏洞利用工具于是尝试编写这个exp,对编程不熟悉的可以看看我的Go......