Skip to content

Commit

Permalink
lots of additions
Browse files Browse the repository at this point in the history
  • Loading branch information
joshmh committed Apr 29, 2011
1 parent 743498a commit 0bd7791
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 30 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib/btc_trader/strategies/*
7 changes: 7 additions & 0 deletions btc_trader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')

require 'btc_trader/engine'

e = BtcTrader::Engine.new 'data/historical.csv'
e.run
puts "ROR: #{'%.2f%' % (e.trader.ror * 100)}, ROR (less fees): #{'%.2f%' % (e.trader.ror_no_fee * 100)}, Trade Count: #{e.trader.trade_count}"
48 changes: 19 additions & 29 deletions lib/btc_trader/engine.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
require 'csv'
require 'metrics_manager'
require 'indicators_manager'
require 'trader'
require 'btc_trader/metrics_manager'
require 'btc_trader/indicators_manager'
require 'btc_trader/trader'
require 'btc_trader/strategies/simple_sma_trader'

module BtcTrader
class HistoricalRecord
Expand All @@ -15,46 +16,35 @@ def initialize(hash)
end

class HistoricalData
def initialize
@data = []
def initialize(file)
@file = file
end

def push(record)
@data << record
end


def each
@data.each {|rec| yield rec }
cutoff = DateTime.parse('2010-11-1')
CSV.foreach(@file) do |row|
rec = HistoricalRecord.new( :price => row[1].to_f,
:volume => row[2].to_f, :time => DateTime.strptime(row[0], '%s') )
next if rec.time < cutoff
yield rec
end
end
end

class Engine
attr_reader :trader

def initialize(data)
@data = HistoricalData.new
@metrics = MetricsManager.new
@indicators = IndicatorsManager.new
@trader = Trader.new @indicators
parse_historical_data(data)
@data = HistoricalData.new data
@trader = Strategies::SimpleSmaTrader.new 10_000
# @trader = Strategies::BuyAndHoldTrader.new 10_000
end

def run
@data.each do |rec|
@metrics.update! rec
@indicators.update! rec
@trader.execute! rec
end
end

private

def parse_historical_data(data)
CSV.foreach(data) do |row|
@data.push HistoricalRecord.new( :price => row[1], :volume => row[2], :time => DateTime.strptime(row[0], '%s') )
end
end

end
end

e = BtcTrader::Engine.new 'data/historical.csv'
e.run
67 changes: 67 additions & 0 deletions lib/btc_trader/trader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module BtcTrader
class Trader
attr_reader :cash_balance, :btc_balance, :price, :trade_count

TRADE_FEE = 0.0065
TRADE_FEE_MULTIPLIER = 1 - TRADE_FEE

def initialize(initial_balance)
@cash_balance = initial_balance.to_f
@btc_balance = 0.0
@initial_balance = @cash_balance
@total_fees = 0.0
@trade_count = 0
initialize_strategy
end

def initialize_strategy; end # NO-OP

def execute!(rec)
@previous_price = @price
@previous_time = @time

@price = rec.price
@time = rec.time

execute_strategy!
end

def buy(amount)
raise "Order exceeds balance" if amount > @cash_balance
@cash_balance -= amount
btc = amount / @price
@btc_balance += btc * TRADE_FEE_MULTIPLIER
@total_fees += btc * TRADE_FEE * @price
@trade_count += 1
end

def sell(amount)
@btc_balance -= amount
cash = amount * @price
@cash_balance += cash * TRADE_FEE_MULTIPLIER
@total_fees += cash * TRADE_FEE
@trade_count += 1
end

def equity
@cash_balance + @btc_balance * @price
end

def ror
(equity - @initial_balance).to_f / @initial_balance
end

def ror_no_fee
(equity + @total_fees - @initial_balance).to_f / @initial_balance
end
end

# A trivial example that buys at the outset and hold until the end
module Strategies
class BuyAndHoldTrader < Trader
def execute_strategy!
buy cash_balance if @cash_balance > 0
end
end
end
end
3 changes: 2 additions & 1 deletion test/indicators/simple_moving_average_test.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..', '/lib')
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..', 'lib')
require 'rubygems'
require 'minitest/autorun'
require 'btc_trader/indicators_manager'
Expand All @@ -14,6 +14,7 @@ def test_basic
assert_equal 10, @sma.value

assert_equal 8.8, @sma.update!(4)
assert_equal 8.8, @sma.value
end

def test_partial
Expand Down

0 comments on commit 0bd7791

Please sign in to comment.