def test_writeln(self): log = Log() log.clear() log.writeln('World!') with open(log.file, mode='r', encoding='utf-8') as f: s = f.read() self.assertEqual(s, 'World!\n')
def test_println(self): log = Log() log.clear() log.println('Hello!') with open(log.file, mode='r', encoding='utf-8') as f: s = f.read() self.assertEqual(s, 'Hello!\n')
Astar_Hybrid_Planning_online(config, iteration, log, num) reinitial_flag = 2 PathInitial(config, reinitial_flag, iteration, log, num) # SC # Astar_Sensor_Config_online(config, iteration, log, num) reinitial_flag = 2 PathInitial(config, reinitial_flag, iteration, log, num) # PP Astar_Path_Planning_online(config, iteration, log, num) reinitial_flag = 2 PathInitial(config, reinitial_flag, iteration, log, num) log_tmp.clear() # num = 0 # # while sum_ref_initial > sum_plan_last: # while num == 0: # num += 1 # refpath, len_refpath, sum_ref, planpath, len_planpath, sum_plan, no_solution_flag = PathInitial(config, reinitial_flag, iteration, # log) # sum_online_plan, len_trajectory_plan, num_intruder_plan, sum_pre, len_trajectory_ref, num_intruder_ref = Astar_Hybrid_Planning_online( # config, iteration, log) # reinitial_flag = 0 # sum_ref_initial = sum_ref # if num > 30: # log.info("Error to be trapped!") # break #
class Daemon(): """ The daemon: - Manages account balance, margin, risk. - Accepts and rejects trade opportunities. - Forcefully close trades as needed (e.g. during shutdown) """ # Initialize log. Log.clear() # diagnostic info DB.execute('INSERT INTO startups (timestamp) VALUES (NOW())') # flag to shut down stopped = False # opportunity pool opportunities = Opportunities() #Initialize strategies. fifty = Fifty(tp_price_diff=0.1, sl_price_diff=0.1) strategies = [] strategies.append(fifty) # Specify the backup strategy. backup_strategy = fifty msg_base = '' # user interface template @classmethod def num_strategies_with_positions(cls): sum = 0 for s in cls.strategies: if s.get_number_positions() > 0: sum += 1 return sum @classmethod def num_strategies_with_no_positions(cls): return len(cls.strategies) - cls.num_strategies_with_positions() @classmethod def _curses_init(cls, stdcsr): # initialize curses curses.echo() # echo key presses stdcsr.nodelay(1) # non-blocking window stdcsr.clear() # clear screen cls.msg_base = '\n' if Config.live_trading: cls.msg_base += 'LIVE TRADING\n' else: cls.msg_base += 'Simulation.\n' cls.msg_base += 'Press q to shut down.\n' cls.msg_base += 'Press m to monitor.\n\n' cls.msg_base += 'Account balance: {}\n' cls.msg_base += '>' stdcsr.addstr(cls.msg_base) stdcsr.refresh() # redraw """ refresh user interface TODO: this waits for the REST calls to return. Too slow. """ @classmethod def _curses_refresh(cls, stdcsr): ch = stdcsr.getch() # get one char if ch == 113: # q == quit stdcsr.addstr('\nInitiating shutdown...\n') stdcsr.refresh() # redraw curses.nocbreak() stdcsr.keypad(False) #curses.echo() curses.endwin() # restore terminal cls.shutdown() elif ch == 109: # m == monitor account_id = Config.account_id balance = Broker.get_balance(account_id) msg = cls.msg_base.format(balance) stdcsr.clear() stdcsr.addstr(msg) stdcsr.refresh() # redraw @classmethod def run(cls, stdcsr): """Returns: void This is the main program loop. """ # initialize user interface cls._curses_init(stdcsr) # Read in existing trades while not cls.stopped and cls.recover_trades() == None: Log.write('"daemon.py" run(): Recovering trades...') cls._curses_refresh(stdcsr) # logging if Config.live_trading: Log.write('"daemon.py" start(): Using live account.') else: Log.write('"daemon.py" start(): Using practice mode.') """ Main loop: 1. Gather opportunities from each strategy. 2. Decide which opportunities to execute. 3. Clear the opportunity list. """ while not cls.stopped: # refresh user interface cls._curses_refresh(stdcsr) # Let each strategy suggest an order for s in cls.strategies: new_opp = s.refresh() if new_opp == None: Log.write( 'daemon.py run(): {} has nothing to offer now.'.format( s.get_name())) pass else: cls.opportunities.push(new_opp) # Decide which opportunity (or opportunities) to execute Log.write('"daemon.py" run(): Picking best opportunity...') best_opp = cls.opportunities.pick() if best_opp == None: # Nothing is being suggested. pass else: # An order was suggested by a strategy, so place the order. # Don't use all the money available. SLIPPAGE_WIGGLE = 0.95 ###available_money = Broker.get_margin_available(Config.account_id) * SLIPPAGE_WIGGLE available_money = 100 # USD - testing # Get the current price of one unit. instrument_price = 0 Log.write('best opp: {}'.format(best_opp)) go_long = best_opp.order.units > 0 if go_long: instrument_price = Broker.get_ask( best_opp.order.instrument) else: instrument_price = Broker.get_bid( best_opp.order.instrument) # How much leverage available: margin_rate = Broker.get_margin_rate(best_opp.order.instrument) # TODO: A bit awkward, but overwrite the existing value that was used to # determine long/short. units = available_money units /= cls.num_strategies_with_no_positions( ) # save money for other strategies units /= margin_rate units = int(units) # floor if units <= 0: # verify Log.write('daemon.py run(): units <= 0') raise Exception # abort if not go_long: # negative means short units = -units best_opp.order.units = units Log.write('daemon.py run(): Executing opportunity:\n{}'.format( best_opp)) order_result = Broker.place_order(best_opp.order) # Notify the strategies. if 'orderFillTransaction' in order_result: try: opened_trade_id = order_result['orderFillTransaction'][ 'tradeOpened']['tradeID'] best_opp.strategy.trade_opened( trade_id=opened_trade_id) except: Log.write( 'daemon.py run(): Failed to extract opened trade from order result:\n{}' .format(order_result)) raise Exception elif 'tradesClosed' in order_result: try: for trade in order_result['orderFillTransaction'][ 'tradesClosed']: best_opp.strategy.trade_closed( trade_id=trade['tradeID']) except: Log.write( 'daemon.py run(): Failed to extract closed trades from order result:\n{}' .format(order_result)) raise Exception elif 'tradeReduced' in order_result: try: closed_trade_id = order_result['orderFillTransaction'][ 'tradeReduced']['tradeID'] best_opp.strategy.trade_reduced( closed_trade_id, instrument_id=Instrument.get_id_from_name( order_result['instrument'])) except: Log.write( 'daemon.py run(): Failed to extract reduced trades from order result:\n{}' .format(order_result)) raise Exception else: Log.write( '"daemon.py" run(): Unrecognized order result:\n{}'. format(order_result)) raise Exception """ Clear opportunity list. Opportunities should be considered to exist only in the moment, so there is no need to save them for later. """ cls.opportunities.clear() """ Shutdown stuff. This runs after shutdown() is called, and is the last code that runs before returning to algo.py. """ DB.shutdown() # atexit() used in db.py, but call to be safe. @classmethod def shutdown(cls): """ Stop daemon. TODO: * set SL and TP * write diagnostic info to db """ Log.write('"daemon.py" shutdown(): Shutting down daemon.') cls.stopped = True @classmethod def recover_trades(cls): """Returns: None on failure, any value on success See if there are any open trades, and resume babysitting. - If trades are opened without writing their info to the db, the trade cannot be distributed back to the strategy that opened it, because it is unknown what strategy placed the order. This could be solved by writing to the db before placing the order, synchronously. However if placing the order failed, then the database record would have to be deleted, and this would be messy. Instead, designate a backup strategy that adopts orphan trades. """ # Get trades from broker. open_trades_broker = Broker.get_open_trades() # instance of <Trades> if open_trades_broker == None: Log.write( 'daemon.py recover_trades(): Broker.get_open_trades() failed.') return None # Delete any trades from the database that are no longer open. # First, ignore trades that the broker has open. db_trades = DB.execute('SELECT trade_id FROM open_trades_live') Log.write( '"daemon.py" recover_trades():\ndb open trades: {}\nbroker open trades: {}' .format(db_trades, open_trades_broker)) for index, dbt in enumerate(db_trades): # O(n^3) for otb in open_trades_broker: if str(dbt[0]) == str(otb.trade_id): # compare trade_id del db_trades[index] # The remaining trades are in the "open trades" db table, but # the broker is not listing them as open. # They may have closed since the daemon last ran; confirm this. # Another cause is that trades are automatically removed from # Oanda's history after much time passes. for dbt in db_trades: if Broker.is_trade_closed(dbt[0])[0]: # Trade is definitely closed; update db. Log.write( '"daemon.py" recover_trades(): Trade {} is closed. Deleting from db.' .format(dbt[0])) else: # Trade is in "open trades" db table and the broker # says the trade is neither open nor closed. DB.bug('Trade w/ID ({}) is neither open nor closed.'.format( dbt[0])) Log.write('"daemon.py" recover_trades(): Trade w/ID (', '{}) is neither open nor closed.'.format(dbt[0])) DB.execute( 'DELETE FROM open_trades_live WHERE trade_id="{}"'.format( dbt[0])) """ Fill in info not provided by the broker, e.g. the name of the strategy that opened the trade. It's possible that a trade will be opened then the system is unexpectedly terminated before info about the trade can be saved to the database. Thus a trade may not have a corresponding trade in the database. """ for i in range(0, len(open_trades_broker)): broker_trade = open_trades_broker[i] db_trade_info = DB.execute( 'SELECT strategy, broker FROM open_trades_live WHERE trade_id="{}"' .format(broker_trade.trade_id)) if len(db_trade_info) > 0: # Verify broker's info and database info match, just to be safe. # - broker name if db_trade_info[0][1] != broker_trade.broker_name: Log.write( '"daemon.py" recover_trades(): ERROR: "{}" != "{}"'. format(db_trade_info[0][1], broker_trade.broker_name)) raise Exception # set strategy broker_trade.strategy = None # TODO: use a different default? for s in cls.strategies: if s.get_name == db_trade_info[0][0]: broker_trade.strategy = s # reference to class instance else: # Trade in broker but not db. # Maybe the trade was opened manually. Ignore it. # Remove from list. open_trades_broker = open_trades_broker[ 0:i] + open_trades_broker[i + 1:len( open_trades_broker)] # TODO: optimize speed # Distribute trades to their respective strategy modules for broker_trade in open_trades_broker: if broker_trade.strategy != None: # Find the strategy that made this trade and notify it. for s in cls.strategies: if broker_trade.strategy.get_name() == s.get_name(): s.adopt(broker_trade.trade_id) open_trades_broker.remove(broker_trade.trade_id) break else: # It is not known what strategy opened this trade. # One possible reason is that the strategy that opened the # trade is no longer open. # Assign it to the backup strategy. Log.write( '"daemon.py" recover_trades(): Assigning trade ', ' ({}) to backup strategy ({}).'.format( broker_trade.trade_id, cls.backup_strategy.get_name())) cls.backup_strategy.adopt(broker_trade.trade_id) return 0 # success
def main(): """最初に実行する主な関数だと思ってくれだぜ☆(^~^)""" # 説明を出そうぜ☆(^~^) log = Log() log.clear() # 最初は全部のコマンドを実装できないが、だんだん増やしていけだぜ☆(^~^) log.println("""きふわらべの〇×ゲーム コマンド: `do 7` - 手番のプレイヤーが、 7 番地に印を付けます。 `go` - コンピューターが次の1手を示します。 `info-off` - info出力なし。 `info-on` - info出力あり(既定)。 `pos` - 局面表示。 `position xfen 3/3/3 o moves 5 1 2 8 4 6 3 7 9` - 初期局面と棋譜を入力。 `undo` - 1手戻します。 `uxi` - 'uxiok tic-tac-toe {protocol-version}' を返します。 `xfen` - 現局面のxfen文字列表示。 """) # 初期局面 pos = Position() # info_enable は 'computer_player.py' を実装してから、ここに追加しろだぜ☆(^~^) info_enable = True # [Ctrl]+[C] でループを終了 while True: # まず最初に、コマンドライン入力を待機しろだぜ☆(^~^) line = input() # コマンドライン☆(^~^) p は parser の意味で使ってるぜ☆(^~^) p = CommandLineParser(line) # 本当は よく使うコマンド順に並べた方が高速だが、先に見つけた方が選ばれるので後ろの方を漏らしやすくて むずかしいし、 # だから、アルファベット順に並べた方が見やすいぜ☆(^~^) if p.starts_with('do'): p.go_next_to('do ') if p.rest != '': UxiProtocol.do(pos, p.rest, log) # go は 'computer_player.py' を実装してから、ここに追加しろだぜ☆(^~^) elif p.starts_with("go"): search = Search(pos.friend, pos.pieces_num, info_enable) (addr, result) = SearchComputer.go(pos, search, log) if addr is not None: log.println( f'info result={result} nps={SearchPerformance.nps(search)}' ) log.println(f'bestmove {addr}') else: log.println('resign') # info-off は 'computer_player.py' を実装してから、ここに追加しろだぜ☆(^~^) elif p.starts_with('info-off'): info_enable = False # info-on は 'computer_player.py' を実装してから、ここに追加しろだぜ☆(^~^) elif p.starts_with('info-on'): info_enable = True elif p.starts_with('position'): p.go_next_to('position ') if p.rest != '': pos = UxiProtocol.from_xfen(p.rest, log) elif p.starts_with('pos'): log.println(pos.pos()) elif p.starts_with('quit'): return elif p.starts_with('undo'): UxiProtocol.undo(pos) elif p.starts_with('uxi'): log.println('uxiok tic-tac-toe v20200704.0.0') elif p.starts_with('xfen'): log.println(UxiProtocol.to_xfen(pos)) else: log.println(f'Debug | Invalid command=|{p.rest}|')
import time from log import Log from look_and_model import Piece, GameResult, Position, Search from position import PositionHelper from command_line_parser import CommandLineParser from uxi_protocol import UxiProtocol from win_lose_judgment import WinLoseJudgment from performance_measurement import SearchPerformance from computer_player import SearchComputer # しょっぱなにプログラムが壊れてないかテストしているぜ☆(^~^) # こんなとこに書かない方がいいが、テストを毎回するのが めんどくさいんで 実行するたびにテストさせているぜ☆(^~^) # Step 1. log = Log() log.clear() log.writeln('Hello, world!!') log.println('こんにちわ、世界!!') # こんにちわ、世界!! # Step 2. log.println(f'Nought=|{Piece.NOUGHT}|') # Nought=|o| log.println(f'Cross =|{Piece.CROSS}|') # Cross =|x| log.println(f'Win =|{GameResult.WIN}|') # Win =|win| log.println(f'Draw =|{GameResult.DRAW}|') # Draw =|draw| log.println(f'Lose =|{GameResult.LOSE}|') # Lose =|lose|
def test_clear(self): log = Log() log.clear() with open(log.file, mode='r', encoding='utf-8') as f: s = f.read() self.assertEqual(s, '')