├── .gitattributes ├── README.md ├── algorithm ├── NSGA2Selection.py ├── multiObjectiveGA.py └── tools.py ├── dataProcessing └── dataProcessing.py ├── processedData ├── minmaxValue.xlsx ├── returns.xlsx └── turnovers.xlsx ├── resultData ├── result.xlsx └── result2.xlsx └── rowData ├── 000001_price.xlsx ├── 000002_price.xlsx ├── 000046_price.xlsx ├── 000858_price.xlsx ├── 002001_price.xlsx ├── 002008_price.xlsx ├── 002236_price.xlsx ├── 002304_price.xlsx ├── 002384_price.xlsx ├── 600009_price.xlsx ├── 600690_price.xlsx └── 600885_price.xlsx /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Portfolio-Optimization-Using-NSGA2-with-Python 2 | See more information about specific algorithm and problem, you can click 3 |
4 |
5 | ## Notification 6 | Because of the research issues, `mutation.py`, `crossover`,`repair.py` will not be upload to the Github for the moment, you can design its by yourself and there enormous documents which can instrust you. 7 |
8 |
9 | ## Row Data 10 | the `rowData` file save all the row data. Specifically, those data include all the daily transaction data for 12 chinese stock bwteen 2014 to 2016. the data are derived from the Straight Flush software. 11 |
12 |
13 | ## Code 14 | `dataProcessing.py`: Process row data set and output result.
15 | `NSGA2Selection.py`: Describe and realize NSGA-Ⅱ algorithm using for portfolio optimization problem.
16 | `multiObjectiveGA.py`:Main module to realize GA loop.
17 | `tools.py`:Save some tool functions.
18 |
19 | ## Usage 20 | After adding `mutation.py`,`crossover.py` and `repair.py` appropriately, you can run `multiObjcetive.py` module to excute GA loop. Of course, you can change the parameters to the see whether there has any difference. 21 | -------------------------------------------------------------------------------- /algorithm/NSGA2Selection.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | NSGA2 selection 4 | """ 5 | import pandas as pd 6 | import numpy as np 7 | 8 | #compute the expectation of the returns of the portfolio 9 | def expectation(returns,weights): 10 | eArray=np.array(returns.mean()) 11 | return np.dot(eArray,weights.T) 12 | 13 | #compute the variance of the returns of the portfolio 14 | def variance(returns,weights): 15 | return np.dot(weights.T, np.dot(returns.cov()*len(returns.index),weights)) 16 | 17 | #compute the skewness of the returns of the portfolio 18 | def turnover(turnovers,weights): 19 | tArray=np.array(turnovers.mean()) 20 | return np.dot(tArray,weights.T) 21 | 22 | #generate value set for every objective 23 | def objectiveValueSet(population,populationSize,fun,data): 24 | valueList=[0 for i in range(populationSize)] 25 | for i in range(populationSize): 26 | valueList[i]=fun(data,np.array(population[i][0])) 27 | return valueList 28 | 29 | #Fast Nondominated Sorting Approach 30 | def NSGA(population,populationSize,returns,turnovers): 31 | #build list and compute return,variance,turnover rate for every entity in the population 32 | returnList=objectiveValueSet(population,populationSize,expectation,returns) 33 | varianceList=objectiveValueSet(population,populationSize,variance,returns) 34 | turnoverList=objectiveValueSet(population,populationSize,turnover,turnovers) 35 | 36 | #define the dominate set Sp 37 | dominateList=[set() for i in range(populationSize)] 38 | #define the dominated set 39 | dominatedList=[set() for i in range(populationSize)] 40 | #compute the dominate and dominated entity for every entity in the population 41 | for i in range(populationSize): 42 | for j in range(populationSize): 43 | if returnList[i]> returnList[j] and varianceList[i]turnoverList[j]: 44 | dominateList[i].add(j) 45 | 46 | elif returnList[i]< returnList[j] and varianceList[i]>varianceList[j] and turnoverList[i]=0: 55 | front=[] 56 | for i in range(len(dominatedList)): 57 | if dominatedList[i]==0: 58 | front.append(i) 59 | NDFSet.append(front) 60 | for i in range(len(dominatedList)): 61 | dominatedList[i]=dominatedList[i]-1 62 | return NDFSet 63 | 64 | #crowded distance 65 | def crowdedDistance(population,Front,minmax,returns,turnovers): 66 | #create distance list to save the information of crowded for every entity in front 67 | distance=pd.Series([float(0) for i in range(len(Front))], index=Front) 68 | #save information of weight for every entity in front 69 | FrontSet=[] 70 | for i in Front: 71 | FrontSet.append(population[i]) 72 | 73 | #compute and save objective value for every entity in front 74 | returnsList=objectiveValueSet(FrontSet,len(FrontSet),expectation,returns) 75 | varianceList=objectiveValueSet(FrontSet,len(FrontSet),variance,returns) 76 | turnoverList=objectiveValueSet(FrontSet,len(FrontSet),turnover,turnovers) 77 | returnsSer=pd.Series(returnsList,index=Front) 78 | varianceSer=pd.Series(varianceList,index=Front) 79 | turnoverSer=pd.Series(turnoverList,index=Front) 80 | #sort value 81 | returnsSer.sort_values(ascending=False,inplace=True) 82 | varianceSer.sort_values(ascending=False,inplace=True) 83 | turnoverSer.sort_values(ascending=False,inplace=True) 84 | #set the distance for the entities which have the min and max value in every objective 85 | distance[returnsSer.index[0]]=1000 86 | distance[returnsSer.index[-1]]=1000 87 | distance[varianceSer.index[0]]=1000 88 | distance[varianceSer.index[-1]]=1000 89 | distance[turnoverSer.index[0]]=1000 90 | distance[turnoverSer.index[-1]]=1000 91 | for i in range(1,len(Front)-1): 92 | distance[returnsSer.index[i]]=distance[returnsSer.index[i]]+(returnsSer[returnsSer.index[i-1]]-returnsSer[returnsSer.index[i+1]])/(minmax.iloc[0,1]-minmax.iloc[0,0]) 93 | distance[varianceSer.index[i]]+=(varianceSer[varianceSer.index[i-1]]-varianceSer[varianceSer.index[i+1]])/(minmax.iloc[1,1]-minmax.iloc[1,0]) 94 | distance[turnoverSer.index[i]]+=(turnoverSer[turnoverSer.index[i-1]]-turnoverSer[turnoverSer.index[i+1]])/(minmax.iloc[2,1]-minmax.iloc[2,0]) 95 | distance.sort_values(ascending=False,inplace=True) 96 | return distance 97 | #crowded compare operator 98 | def crowdedCompareOperator(population,populationSize,NDFSet,minmax,returns,turnovers): 99 | newPopulation=[] 100 | #save the information of the entity the new population have 101 | count=0 102 | #save the information of the succession of the front 103 | number=0 104 | while countu: 34 | t=random.choice(label) 35 | entity[t]=random.uniform(l,u) 36 | n-=entity[t] 37 | label.remove(t) 38 | elif n0: 13 | stocklist.append(1) 14 | else: 15 | stocklist.append(0) 16 | if len(population[i])==1: 17 | population[i].append(stocklist) 18 | else: 19 | population[i][1]=stocklist 20 | return population 21 | 22 | def yagersEntropy(porprotion,n): 23 | H=0 24 | for i in range(n): 25 | H+=abs(porprotion[i]-1/n) 26 | 27 | return H -------------------------------------------------------------------------------- /dataProcessing/dataProcessing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | data process 4 | """ 5 | import pandas as pd 6 | 7 | #define function to output processed file 8 | def outputFile(data,source): 9 | data.to_excel(source+'.xlsx',encoding='utf-8') 10 | 11 | name=['000002','600690','002001','600009','000001','002008','002236','002384','002304','600885','000046','000858'] 12 | suffix='_price' 13 | 14 | returnData=pd.DataFrame() 15 | turnoverData=pd.DataFrame() 16 | for i in range(len(name)): 17 | data=pd.read_excel('../rowData/'+name[i]+suffix+'.xlsx') 18 | data.index=pd.to_datetime(data['时间']) 19 | returnData[name[i]]=data['涨幅'] 20 | turnoverData[name[i]]=data['换手%'] 21 | 22 | returnData=returnData.fillna(0) 23 | turnoverData=turnoverData.fillna(0) 24 | outputFile(returnData,'../processedData/returns') 25 | outputFile(turnoverData,'../processedData/turnovers') 26 | 27 | 28 | -------------------------------------------------------------------------------- /processedData/minmaxValue.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/processedData/minmaxValue.xlsx -------------------------------------------------------------------------------- /processedData/returns.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/processedData/returns.xlsx -------------------------------------------------------------------------------- /processedData/turnovers.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/processedData/turnovers.xlsx -------------------------------------------------------------------------------- /resultData/result.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/resultData/result.xlsx -------------------------------------------------------------------------------- /resultData/result2.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/resultData/result2.xlsx -------------------------------------------------------------------------------- /rowData/000001_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/000001_price.xlsx -------------------------------------------------------------------------------- /rowData/000002_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/000002_price.xlsx -------------------------------------------------------------------------------- /rowData/000046_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/000046_price.xlsx -------------------------------------------------------------------------------- /rowData/000858_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/000858_price.xlsx -------------------------------------------------------------------------------- /rowData/002001_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/002001_price.xlsx -------------------------------------------------------------------------------- /rowData/002008_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/002008_price.xlsx -------------------------------------------------------------------------------- /rowData/002236_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/002236_price.xlsx -------------------------------------------------------------------------------- /rowData/002304_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/002304_price.xlsx -------------------------------------------------------------------------------- /rowData/002384_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/002384_price.xlsx -------------------------------------------------------------------------------- /rowData/600009_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/600009_price.xlsx -------------------------------------------------------------------------------- /rowData/600690_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/600690_price.xlsx -------------------------------------------------------------------------------- /rowData/600885_price.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiaruiFeng/Portfolio-Optimization-Using-NSGA2-with-Python/165ced3d975d4eda9de2fffb11ea0cea7b1d1408/rowData/600885_price.xlsx --------------------------------------------------------------------------------