相場商売

トレーディングビジネスあれこれ

17章

売買ルールつくり。

とりあえず作り終え、チェックファイルも作ったが、エラーが出た。

rubyのyieldは匿名関数に近いということなので、
rule.pyの_with_valid_indicatorsの引数に式を取るようにしたのだが、
それがどうもまずく、self.check_long(index)の評価の段階で
__getitem__のチェックが入り、Noneなので
ValueErrorが出てしまい止まってしまう。

結局entry.pyのcheck_long_entryの部分を以下のように変えることで動くようになった。
他のファイルはまだチェックしてないが同じようにしないとダメだろう。

    def check_long_entry(self, index):
        try:
            return self._with_valid_indicators(self.check_long(index))
        except ValueError:
            pass

    def check_short_entry(self, index):
        try:
            return self._with_valid_indicators(self.check_short(index))
        except ValueError:
            pass

以下順番に
estrangement_entry.py
estrangement_exit.py
stop_out_exit.py
average_true_range_stop.py
moving_average_direction_filter.py
estrangement_entry_check.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from entry import Entry
from estrangement import Estrangement

# 移動平均乖離率による仕掛けクラス
# 前日の終値が、n日移動平均からx%離れたら寄付きで仕掛ける
class EstrangementEntry(Entry):
    
    def __init__(self, params):
        self.span = params['span']
        self.rate = params['rate']
        
    def calculate_indicators(self):
        self.estrangement = Estrangement(self.stock, {'span': self.span}).calculate()
        return self.estrangement
    
    def check_long(self, index):
        if self.estrangement[index - 1] < (-1) * self.rate:
            return self._enter_long(index, self.stock.open_prices()[index], 'open')
            
    def check_short(self, index):
        if self.estrangement[index - 1] > self.rate:
            return self._enter_short(index, self.stock.open_prices()[index], 'open') 
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from exit import Exit
from estrangement import Estrangement

# 移動平均乖離率による手仕舞いクラス
# 前日の終値が、n日移動平均からx%以内のとき寄付きで手仕舞う
class EstrangementExit(Exit):
    
    def __init__(self, params):
        self.span = params['span']
        self.rate = params['rate']
        
    def calculate_indicators(self):
        self.estrangement = Estrangement(self.stock, {'span': self.span}).calculate()
    
    def check_long(self, trade, index):
        if self.estrangement[index - 1] > (-1) * self.rate:
            self._exit(trade, index, self.stock.open_prices()[index], 'open')
            
    def check_short(self, trade, index):
        if self.estrangement[index - 1] < self.rate:
            self._exit(trade, index, self.stock.open_prices()[index], 'open') 
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from exit import Exit

# ストップアウトクラス
# 価格がストップに掛かったら手仕舞う
# ストップに掛かった瞬間、即座に手仕舞う
# 寄付きで掛かったら寄付きで、
# 場中に掛かったら場中に手仕舞う
class StopOutExit(Exit):

    def check_long(self, trade, index):
        stop = trade.stop
        price = self.stock.prices[index]
        if stop >= price['low']:
            if stop >= price['open']:
                price, time = price['open'], 'open'
            else:
                price, time = stop, 'in_session'
        self._exit(trade, index, price, time)                
            
    def check_short(self, trade, index):
        stop = trade.stop
        price = self.stock.prices[index]
        if stop <= price['high']:
            if stop <= price['open']:
                price, time = price['open'], 'open'
            else:
                price, time = stop, 'in_session'
        self._exit(trade, index, price, time)           
            
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from stop import Stop
from average_true_range import AverageTrueRange
import Tick

# 真の値幅の移動平均(ATR)に基づくストップクラス
# 仕掛値から
# 買いでは、n日間のATRのx倍、下に
# 売りでは、n日間のATRのx倍、上に
# ストップを置く
class AverageTrueRangeStop(Stop):
    # span  ATRの期間
    # ratio ATRの何倍か
    def __init__(self, params):
        self.span = params['span']
        self.ratio = params['ratio'] or 1
    
    def calculate_indicators(self):
        self.average_true_range = AverageTrueRange(self.stock, {'span': self.span}).calculate()
        
    # 仕掛値からn日ATR(前日)のx倍下に行ったところにストップ
    def stop_price_long(self, position, index):
        Tick.truncate(position.entry_price - self._range(index))
    
    # 仕掛値からn日ATR(前日)のx倍上に行ったところにストップ        
    def stocp_price_short(self, position, index):
        Tick.ceil(position.entry_price + self._range(index))
        
    def _range(self, index):
        self.average_true_range[index - 1] * self.ratio         
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from filter import Filter
from moving_average_direction import MovingAverageDirection

# 移動平均の方向フィルタークラス
# 前日の移動平均が上昇中のときは、買いからのみ入る
# 前日の移動平均が下降中のときは、売りからのみ入る
# 前日の移動平均が横ばいのときは、仕掛けない
class MovingAverageDirectionFilter(Filter):

    def __init__(self, params):
        self.span = params['span']
    
    def calculate_indicators(self):
        self.moving_average_direction = MovingAverageDirection(self.stock, {'span': self.span}).calculate()
        
    def filter(self, index):
        if self.moving_average_direction[index - 1] == 'up':
            return 'long_only'
        elif self.moving_average_direction[index - 1] == 'down':
            return 'short_only'
        elif self.moving_average_direction[index - 1] == 'flat':
            return 'no_entry'
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from estrangement_entry import EstrangementEntry
from text_to_stock import TextToStock

tts = TextToStock({'data_dir':'data', 'stock_list':'tosho_list.txt', 'market_section':'東証1部'})
tts.frm = '2011/01/04'
tts.to   = '2011/06/30'

stock = tts.generate_stock(8604)

est_entry = EstrangementEntry({'span': 20, 'rate':5})
est_entry.stock = stock
est_entry.calculate_indicators()

real_signals = [None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,'long',None,None,None,None,None,None,None,None,None,None,'short','short',None,None,None,None,None,None,None,None,None,None,'long','long',None,'long','long','long','long','long','long','long',None,'long','long','long','long','long','long',None,'long',None,'long','long','long',None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,'long',None,None,None,None,'long','long',None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,'long','long','long',None,None,None,None,None,None,None]

for i , sig in enumerate(real_signals):
    calc_signal = est_entry.check_long_entry(i+1) or est_entry.check_short_entry(i+1)
    if calc_signal is None:
        if real_signals[i] is None:
            print('None None')
        else:
            print('None ' + real_signals[i])
    else:
        print(calc_signal.trade_type + ' ' + real_signals[i])
        
print(est_entry.check_long_entry(0))
print(est_entry.check_short_entry(0))