Один довольно простой способ сделать это - использовать pandas:
df = pd.DataFrame(opt)
df = df.drop_duplicates(subset = ["expiry", "strike"])
[ v.dropna().to_dict() for k,v in df.iterrows() ]
Результаты в:
[{'expiry': '2020-06-26', 'strike': 138.5, 'p_bid': 0.4375, 'p_ask': 0.46875},
{'expiry': '2020-06-26', 'strike': 139.0, 'p_bid': 0.6875, 'p_ask': 0.71875},
{'expiry': '2020-07-22', 'strike': 139.0, 'p_bid': 1.015625, 'p_ask': 1.0625}]
Обратите внимание, что при удалении дубликатов я сохраняю первый элемент. Можно легко оставить последний элемент, если это то, что вы хотите, но используя:
df = df.drop_duplicates(subset = ["expiry", "strike"], keep="last")
В этом случае результат:
[{'expiry': '2020-06-26', 'strike': 138.5, 'c_bid': 0.6875, 'c_ask': 0.734375},
{'expiry': '2020-06-26', 'strike': 139.0, 'c_bid': 0.4375, 'c_ask': 0.484375},
{'expiry': '2020-07-22', 'strike': 139.0, 'c_bid': 0.28125, 'c_ask': 0.3125}]
И еще один способ - использовать словарь для уменьшения «похожих» значений:
reduction_dict = {(x["expiry"], x["strike"]):x for x in opt }
list(reduction_dict.values())