├── .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
--------------------------------------------------------------------------------