Here is an example of an expert system for decision making coded in SWI-Prolog.
It takes a sample portfolio, a current asset price list and a risk tolerance profile it can then make decisions regrading selling financial assets based on specific strategy being applied.
These strategies are based on predefined tactics, and the tactics in turn are an application of lists of sell rules.
This an exercise in declarative logic programming, please DO NOT TAKE ANY OF THIS AS INVESTMENT ADVICE.
Currently only some sell rules, tactics and a strategy are implemented, this framework can however be easily extended to encompass a full spectrum trading decision making.
At some point in time I will also extend this post to further describe and document this code. For now you can just head over to https://swish.swi-prolog.org/ paste the code in the online IDE and take it for a spin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
%ASSET LIST asset( name(bitcoin), ticker('BTC'), purchase_price(10), units(100) ). asset( name('Lehman Brothers Holdings Inc.'), ticker('LEH'), purchase_price(1), units(1000) ). asset( name('Deutsche Bank AG'), ticker('DB'), purchase_price(5), units(200) ). %CURRENT PRICE DATA current_price_data([asset(ticker('DB'), price(10)), asset(ticker('LEH'), price(1)), asset(ticker('BTC'), price(10))]). %RISK TOLERANCE PROFILES DATA risk_tolerance_profile( name('takeprofitnoliquidity'), takeprofitpercent(150), liquiditydemand('LOW'), maxportfolioshare(2) ). risk_tolerance_profile( name('takeprofitcapneeded'), takeprofitpercent(150), liquiditydemand('URGENT'), maxportfolioshare(51) ). %active_rtp(takeprofitnoliquidity). active_rtp(takeprofitcapneeded). %HELPER RULES portfolio_total(Total) :- aggregate_all(sum((Price*Units)), (asset(_,ticker(Ticker),_,units(Units)), current_price_data(LIST), member(asset(ticker(Ticker), price(Price)), LIST)), Total). %%SELL RULES sell_rule(test,Arg):- [A1,A2]=Arg, nl,write('[sell_rule(test)]-> Arg1 is: '),write(A1), nl,write('[sell_rule(test)]-> Arg2 is: '),write(A2), nl,write('[sell_rule(test)]-> THE answer is: '),write('42'). sell_rule(takeprofit, Arg):- [Purchse_price, Current_price, TakeprofitPercent, Gain] = Arg, Gain is (Current_price*100)/Purchse_price,Gain > TakeprofitPercent, nl,write('[sell_rule(takeprofit)]-> Gain is: '),write(Gain),write('%'). sell_rule(diversify, Arg):- [Maxportfolioshare,Current_price, Units, TotalPortfolio]=Arg, PortfolioShare is Current_price * Units, PortfolioSharePercent is (PortfolioShare*100/TotalPortfolio), PortfolioSharePercent > Maxportfolioshare, nl,write('[sell_rule(diversify)]-> PortfolioShare is: '), write(PortfolioShare), nl,write('[sell_rule(diversify)]-> PortfolioSharePercent is: '), write(PortfolioSharePercent),write('%'), nl,write('[sell_rule(diversify)]-> Totalportfolio is: '), write(TotalPortfolio), nl,write('[sell_rule(diversify)]-> DIVIRSIFY!'). sell_rule(liquidity, Arg):- [LiquidityDemand|_]=Arg, (LiquidityDemand = 'URGENT'; LiquidityDemand = 'HIGH'), nl,write('[sell_rule(liquidity)]-> LiquidityDemand is: '), write(LiquidityDemand), nl,write('[sell_rule(liquidity)]-> Sell asset!'). %%SELL TACTICS tactic(takeprofit, Asset_ticker) :- %Assemble relative arguments asset(_,ticker( Asset_ticker),purchase_price(Purchse_price),_), current_price_data(PRICELIST), member(asset(ticker(Asset_ticker), price(Current_price)), PRICELIST), %Retrive TakeprofitPercent from risk_tolerance_profile, active_rtp(RTPNAME), risk_tolerance_profile( name(RTPNAME), takeprofitpercent(TakeprofitPercent),_,_), %Evaluate tactic rules Rules= [test, takeprofit], Args = [[1,2],[Purchse_price,Current_price,TakeprofitPercent,_]], maplist(sell_rule(),Rules,Args). tactic(takeprofitIFneeded, Asset_ticker) :- %Assemble relative arguments asset(_,ticker( Asset_ticker),purchase_price(Purchse_price),_), current_price_data(PRICELIST), member(asset(ticker(Asset_ticker), price(Current_price)), PRICELIST), %Retrive TakeprofitPercent from risk_tolerance_profile, %Retrive LiquidityDemand from risk_tolerance_profile, active_rtp(RTPNAME), risk_tolerance_profile( name(RTPNAME), takeprofitpercent(TakeprofitPercent),liquiditydemand(LiquidityDemand),_), %Evaluate tactic rules Rules= [liquidity, takeprofit], Args = [[LiquidityDemand],[Purchse_price,Current_price,TakeprofitPercent,_]], maplist(sell_rule(),Rules,Args). tactic(diversify, Asset_ticker) :- active_rtp(RTPNAME), risk_tolerance_profile(name(RTPNAME),_,_, maxportfolioshare(Maxportfolioshare)), asset(name(Name),ticker( Asset_ticker),_,units(Units)), current_price_data(PRICELIST), member(asset(ticker(Asset_ticker), price(Current_price)), PRICELIST), portfolio_total(TotalPortfolio), Arg=[Maxportfolioshare,Current_price, Units, TotalPortfolio], write('Asset name: '),write(Name), sell_rule(diversify, Arg). %BUY TACTICS %EXECUTE STRATEGY sell_asset(Asset_ticker):- tactic(takeprofit,Asset_ticker); tactic(diversify, Asset_ticker). |