解析的に解く方法もありますが、シミュレーションで近似解を計算するほうが直感的なので、以下にサンプルを載せておきます。
import numpy as np
import pandas as pd
import scipy.stats as stats
x1 = stats.norm.rvs(loc=115,scale= 8.0,size=10000)
x2 = stats.norm.rvs(loc=118,scale= 8.5,size=10000)
x3 = stats.norm.rvs(loc=125,scale=10.0,size=10000)
x4 = stats.norm.rvs(loc=128,scale= 9.0,size=10000)
ALL = pd.DataFrame([x1,x2,x3,x4],index=['x1','x2','x3','x4'])
result = np.argsort(ALL,axis=0)
np.sum((result.loc['x1',:]==0)&(result.loc['x2',:]==1))/10000
上記は、x1,x2,x3,x4のうち、X1が1位x2が2位になる確率を求めるための10000回のシミュレーションです。
上記は、前提としてx1~x4は独立して出現することを置いています。(つまり、x1の値が大きいとx2も大きくなるなどの依存関係がない)これにより、各々を独立してデータを取得したのちに比較しても問題ないことになります。気になるようでしたら、x1,x2,x3,x4の順に乱数を1つ求めるという処理を10000回繰り返すというコードに書き替えてください。
上記は簡易なものなので、もう少し厳密な手続きを踏みつつシミュレーション結果を得たいのであれば、pystanあたりを使うといいかと思います。