Adventures in Prolog, Financial asset trading expert system example.

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.

%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).